aboutsummaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
authorkenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2009-07-29 01:13:20 +0000
committerkenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2009-07-29 01:13:20 +0000
commit80b1d62bfcea65c59e2160da71dad84b1bd19cef (patch)
tree5423b830c53174fec83a7ea01ff0877e11c1ddb6 /java
parentd2fd0638c309113ccae3731a58e30419f522269a (diff)
downloadprotobuf-80b1d62bfcea65c59e2160da71dad84b1bd19cef.tar.gz
protobuf-80b1d62bfcea65c59e2160da71dad84b1bd19cef.tar.bz2
protobuf-80b1d62bfcea65c59e2160da71dad84b1bd19cef.zip
Submit recent changes from internal branch, including "lite mode" for
C++ and Java. See CHANGES.txt for more details.
Diffstat (limited to 'java')
-rw-r--r--java/pom.xml3
-rw-r--r--java/src/main/java/com/google/protobuf/AbstractMessage.java681
-rw-r--r--java/src/main/java/com/google/protobuf/AbstractMessageLite.java321
-rw-r--r--java/src/main/java/com/google/protobuf/ByteString.java76
-rw-r--r--java/src/main/java/com/google/protobuf/CodedInputStream.java224
-rw-r--r--java/src/main/java/com/google/protobuf/CodedOutputStream.java424
-rw-r--r--java/src/main/java/com/google/protobuf/Descriptors.java558
-rw-r--r--java/src/main/java/com/google/protobuf/DynamicMessage.java81
-rw-r--r--java/src/main/java/com/google/protobuf/ExtensionRegistry.java80
-rw-r--r--java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java169
-rw-r--r--java/src/main/java/com/google/protobuf/FieldSet.java910
-rw-r--r--java/src/main/java/com/google/protobuf/GeneratedMessage.java532
-rw-r--r--java/src/main/java/com/google/protobuf/GeneratedMessageLite.java539
-rw-r--r--java/src/main/java/com/google/protobuf/Internal.java194
-rw-r--r--java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java4
-rw-r--r--java/src/main/java/com/google/protobuf/Message.java247
-rw-r--r--java/src/main/java/com/google/protobuf/MessageLite.java331
-rw-r--r--java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java2
-rw-r--r--java/src/main/java/com/google/protobuf/RpcUtil.java13
-rw-r--r--java/src/main/java/com/google/protobuf/ServiceException.java6
-rw-r--r--java/src/main/java/com/google/protobuf/TextFormat.java296
-rw-r--r--java/src/main/java/com/google/protobuf/UninitializedMessageException.java85
-rw-r--r--java/src/main/java/com/google/protobuf/UnknownFieldSet.java389
-rw-r--r--java/src/main/java/com/google/protobuf/WireFormat.java94
-rw-r--r--java/src/test/java/com/google/protobuf/DescriptorsTest.java30
-rw-r--r--java/src/test/java/com/google/protobuf/DynamicMessageTest.java12
-rw-r--r--java/src/test/java/com/google/protobuf/GeneratedMessageTest.java89
-rw-r--r--java/src/test/java/com/google/protobuf/LiteTest.java114
-rw-r--r--java/src/test/java/com/google/protobuf/TestUtil.java1031
-rw-r--r--java/src/test/java/com/google/protobuf/TextFormatTest.java25
-rw-r--r--java/src/test/java/com/google/protobuf/WireFormatTest.java65
31 files changed, 5308 insertions, 2317 deletions
diff --git a/java/pom.xml b/java/pom.xml
index 12787a4b..bf5d206f 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -124,6 +124,9 @@
value="../src/google/protobuf/unittest_optimize_for.proto" />
<arg
value="../src/google/protobuf/unittest_custom_options.proto" />
+ <arg value="../src/google/protobuf/unittest_lite.proto" />
+ <arg value="../src/google/protobuf/unittest_import_lite.proto" />
+ <arg value="../src/google/protobuf/unittest_lite_imports_nonlite.proto" />
</exec>
</tasks>
<testSourceRoot>target/generated-test-sources</testSourceRoot>
diff --git a/java/src/main/java/com/google/protobuf/AbstractMessage.java b/java/src/main/java/com/google/protobuf/AbstractMessage.java
index 53175cdd..e5bdefe3 100644
--- a/java/src/main/java/com/google/protobuf/AbstractMessage.java
+++ b/java/src/main/java/com/google/protobuf/AbstractMessage.java
@@ -30,12 +30,12 @@
package com.google.protobuf;
+import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
-import java.io.FilterInputStream;
import java.io.InputStream;
import java.io.IOException;
-import java.io.OutputStream;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -45,11 +45,12 @@ import java.util.Map;
*
* @author kenton@google.com Kenton Varda
*/
-public abstract class AbstractMessage implements Message {
+public abstract class AbstractMessage extends AbstractMessageLite
+ implements Message {
@SuppressWarnings("unchecked")
public boolean isInitialized() {
// Check that all required fields are present.
- for (FieldDescriptor field : getDescriptorForType().getFields()) {
+ for (final FieldDescriptor field : getDescriptorForType().getFields()) {
if (field.isRequired()) {
if (!hasField(field)) {
return false;
@@ -58,11 +59,12 @@ public abstract class AbstractMessage implements Message {
}
// Check that embedded messages are initialized.
- for (Map.Entry<FieldDescriptor, Object> entry : getAllFields().entrySet()) {
- FieldDescriptor field = entry.getKey();
+ for (final Map.Entry<FieldDescriptor, Object> entry :
+ getAllFields().entrySet()) {
+ final FieldDescriptor field = entry.getKey();
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
if (field.isRepeated()) {
- for (Message element : (List<Message>) entry.getValue()) {
+ for (final Message element : (List<Message>) entry.getValue()) {
if (!element.isInitialized()) {
return false;
}
@@ -83,117 +85,59 @@ public abstract class AbstractMessage implements Message {
return TextFormat.printToString(this);
}
- public void writeTo(CodedOutputStream output) throws IOException {
- for (Map.Entry<FieldDescriptor, Object> entry : getAllFields().entrySet()) {
- FieldDescriptor field = entry.getKey();
- if (field.isRepeated()) {
- List valueList = (List) entry.getValue();
- if (field.getOptions().getPacked()) {
-
- output.writeTag(field.getNumber(),
- WireFormat.WIRETYPE_LENGTH_DELIMITED);
- int dataSize = 0;
- for (Object element : valueList) {
- dataSize += CodedOutputStream.computeFieldSizeNoTag(
- field.getType(), element);
- }
- output.writeRawVarint32(dataSize);
-
- for (Object element : valueList) {
- output.writeFieldNoTag(field.getType(), element);
- }
- } else {
- for (Object element : valueList) {
- output.writeField(field.getType(), field.getNumber(), element);
- }
- }
+ public void writeTo(final CodedOutputStream output) throws IOException {
+ final boolean isMessageSet =
+ getDescriptorForType().getOptions().getMessageSetWireFormat();
+
+ for (final Map.Entry<FieldDescriptor, Object> entry :
+ getAllFields().entrySet()) {
+ final FieldDescriptor field = entry.getKey();
+ final Object value = entry.getValue();
+ if (isMessageSet && field.isExtension() &&
+ field.getType() == FieldDescriptor.Type.MESSAGE &&
+ !field.isRepeated()) {
+ output.writeMessageSetExtension(field.getNumber(), (Message) value);
} else {
- output.writeField(field.getType(), field.getNumber(), entry.getValue());
+ FieldSet.writeField(field, value, output);
}
}
- UnknownFieldSet unknownFields = getUnknownFields();
- if (getDescriptorForType().getOptions().getMessageSetWireFormat()) {
+ final UnknownFieldSet unknownFields = getUnknownFields();
+ if (isMessageSet) {
unknownFields.writeAsMessageSetTo(output);
} else {
unknownFields.writeTo(output);
}
}
- public ByteString toByteString() {
- try {
- ByteString.CodedBuilder out =
- ByteString.newCodedBuilder(getSerializedSize());
- writeTo(out.getCodedOutput());
- return out.build();
- } catch (IOException e) {
- throw new RuntimeException(
- "Serializing to a ByteString threw an IOException (should " +
- "never happen).", e);
- }
- }
-
- public byte[] toByteArray() {
- try {
- byte[] result = new byte[getSerializedSize()];
- CodedOutputStream output = CodedOutputStream.newInstance(result);
- writeTo(output);
- output.checkNoSpaceLeft();
- return result;
- } catch (IOException e) {
- throw new RuntimeException(
- "Serializing to a byte array threw an IOException " +
- "(should never happen).", e);
- }
- }
-
- public void writeTo(OutputStream output) throws IOException {
- CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
- writeTo(codedOutput);
- codedOutput.flush();
- }
-
- public void writeDelimitedTo(OutputStream output) throws IOException {
- CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
- codedOutput.writeRawVarint32(getSerializedSize());
- writeTo(codedOutput);
- codedOutput.flush();
- }
-
private int memoizedSize = -1;
public int getSerializedSize() {
int size = memoizedSize;
- if (size != -1) return size;
+ if (size != -1) {
+ return size;
+ }
size = 0;
- for (Map.Entry<FieldDescriptor, Object> entry : getAllFields().entrySet()) {
- FieldDescriptor field = entry.getKey();
- if (field.isRepeated()) {
- List valueList = (List) entry.getValue();
- if (field.getOptions().getPacked()) {
- int dataSize = 0;
- for (Object element : valueList) {
- dataSize += CodedOutputStream.computeFieldSizeNoTag(
- field.getType(), element);
- }
- size += dataSize;
- size += CodedOutputStream.computeTagSize(field.getNumber());
- size += CodedOutputStream.computeRawVarint32Size(dataSize);
- } else {
- for (Object element : valueList) {
- size += CodedOutputStream.computeFieldSize(
- field.getType(), field.getNumber(), element);
- }
- }
+ final boolean isMessageSet =
+ getDescriptorForType().getOptions().getMessageSetWireFormat();
+
+ for (final Map.Entry<FieldDescriptor, Object> entry :
+ getAllFields().entrySet()) {
+ final FieldDescriptor field = entry.getKey();
+ final Object value = entry.getValue();
+ if (isMessageSet && field.isExtension() &&
+ field.getType() == FieldDescriptor.Type.MESSAGE &&
+ !field.isRepeated()) {
+ size += CodedOutputStream.computeMessageSetExtensionSize(
+ field.getNumber(), (Message) value);
} else {
- size += CodedOutputStream.computeFieldSize(
- field.getType(), field.getNumber(), entry.getValue());
+ size += FieldSet.computeFieldSize(field, value);
}
}
- UnknownFieldSet unknownFields = getUnknownFields();
- if (getDescriptorForType().getOptions().getMessageSetWireFormat()) {
+ final UnknownFieldSet unknownFields = getUnknownFields();
+ if (isMessageSet) {
size += unknownFields.getSerializedSizeAsMessageSet();
} else {
size += unknownFields.getSerializedSize();
@@ -204,14 +148,14 @@ public abstract class AbstractMessage implements Message {
}
@Override
- public boolean equals(Object other) {
+ public boolean equals(final Object other) {
if (other == this) {
return true;
}
if (!(other instanceof Message)) {
return false;
}
- Message otherMessage = (Message) other;
+ final Message otherMessage = (Message) other;
if (getDescriptorForType() != otherMessage.getDescriptorForType()) {
return false;
}
@@ -237,20 +181,21 @@ public abstract class AbstractMessage implements Message {
*/
@SuppressWarnings("unchecked")
public static abstract class Builder<BuilderType extends Builder>
+ extends AbstractMessageLite.Builder<BuilderType>
implements Message.Builder {
// The compiler produces an error if this is not declared explicitly.
@Override
public abstract BuilderType clone();
public BuilderType clear() {
- for (Map.Entry<FieldDescriptor, Object> entry :
+ for (final Map.Entry<FieldDescriptor, Object> entry :
getAllFields().entrySet()) {
clearField(entry.getKey());
}
return (BuilderType) this;
}
- public BuilderType mergeFrom(Message other) {
+ public BuilderType mergeFrom(final Message other) {
if (other.getDescriptorForType() != getDescriptorForType()) {
throw new IllegalArgumentException(
"mergeFrom(Message) can only merge messages of the same type.");
@@ -265,15 +210,15 @@ public abstract class AbstractMessage implements Message {
// TODO(kenton): Provide a function somewhere called makeDeepCopy()
// which allows people to make secure deep copies of messages.
- for (Map.Entry<FieldDescriptor, Object> entry :
+ for (final Map.Entry<FieldDescriptor, Object> entry :
other.getAllFields().entrySet()) {
- FieldDescriptor field = entry.getKey();
+ final FieldDescriptor field = entry.getKey();
if (field.isRepeated()) {
- for (Object element : (List)entry.getValue()) {
+ for (final Object element : (List)entry.getValue()) {
addRepeatedField(field, element);
}
} else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
- Message existingValue = (Message)getField(field);
+ final Message existingValue = (Message)getField(field);
if (existingValue == existingValue.getDefaultInstanceForType()) {
setField(field, entry.getValue());
} else {
@@ -288,24 +233,288 @@ public abstract class AbstractMessage implements Message {
}
}
+ mergeUnknownFields(other.getUnknownFields());
+
return (BuilderType) this;
}
- public BuilderType mergeFrom(CodedInputStream input) throws IOException {
+ @Override
+ public BuilderType mergeFrom(final CodedInputStream input)
+ throws IOException {
return mergeFrom(input, ExtensionRegistry.getEmptyRegistry());
}
- public BuilderType mergeFrom(CodedInputStream input,
- ExtensionRegistry extensionRegistry)
- throws IOException {
- UnknownFieldSet.Builder unknownFields =
+ @Override
+ public BuilderType mergeFrom(
+ final CodedInputStream input,
+ final ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ final UnknownFieldSet.Builder unknownFields =
UnknownFieldSet.newBuilder(getUnknownFields());
- FieldSet.mergeFrom(input, unknownFields, extensionRegistry, this);
+ while (true) {
+ final int tag = input.readTag();
+ if (tag == 0) {
+ break;
+ }
+
+ if (!mergeFieldFrom(input, unknownFields, extensionRegistry,
+ this, tag)) {
+ // end group tag
+ break;
+ }
+ }
setUnknownFields(unknownFields.build());
return (BuilderType) this;
}
- public BuilderType mergeUnknownFields(UnknownFieldSet unknownFields) {
+ /**
+ * Like {@link #mergeFrom(CodedInputStream, UnknownFieldSet.Builder,
+ * ExtensionRegistryLite, Message.Builder)}, but parses a single field.
+ * Package-private because it is used by GeneratedMessage.ExtendableMessage.
+ * @param tag The tag, which should have already been read.
+ * @return {@code true} unless the tag is an end-group tag.
+ */
+ @SuppressWarnings("unchecked")
+ static boolean mergeFieldFrom(
+ final CodedInputStream input,
+ final UnknownFieldSet.Builder unknownFields,
+ final ExtensionRegistryLite extensionRegistry,
+ final Message.Builder builder,
+ final int tag) throws IOException {
+ final Descriptor type = builder.getDescriptorForType();
+
+ if (type.getOptions().getMessageSetWireFormat() &&
+ tag == WireFormat.MESSAGE_SET_ITEM_TAG) {
+ mergeMessageSetExtensionFromCodedStream(
+ input, unknownFields, extensionRegistry, builder);
+ return true;
+ }
+
+ final int wireType = WireFormat.getTagWireType(tag);
+ final int fieldNumber = WireFormat.getTagFieldNumber(tag);
+
+ final FieldDescriptor field;
+ Message defaultInstance = null;
+
+ if (type.isExtensionNumber(fieldNumber)) {
+ // extensionRegistry may be either ExtensionRegistry or
+ // ExtensionRegistryLite. Since the type we are parsing is a full
+ // message, only a full ExtensionRegistry could possibly contain
+ // extensions of it. Otherwise we will treat the registry as if it
+ // were empty.
+ if (extensionRegistry instanceof ExtensionRegistry) {
+ final ExtensionRegistry.ExtensionInfo extension =
+ ((ExtensionRegistry) extensionRegistry)
+ .findExtensionByNumber(type, fieldNumber);
+ if (extension == null) {
+ field = null;
+ } else {
+ field = extension.descriptor;
+ defaultInstance = extension.defaultInstance;
+ }
+ } else {
+ field = null;
+ }
+ } else {
+ field = type.findFieldByNumber(fieldNumber);
+ }
+
+ if (field == null || wireType !=
+ FieldSet.getWireFormatForFieldType(
+ field.getLiteType(),
+ field.getOptions().getPacked())) {
+ // Unknown field or wrong wire type. Skip.
+ return unknownFields.mergeFieldFrom(tag, input);
+ }
+
+ if (field.getOptions().getPacked()) {
+ final int length = input.readRawVarint32();
+ final int limit = input.pushLimit(length);
+ if (field.getLiteType() == WireFormat.FieldType.ENUM) {
+ while (input.getBytesUntilLimit() > 0) {
+ final int rawValue = input.readEnum();
+ final Object value = field.getEnumType().findValueByNumber(rawValue);
+ if (value == null) {
+ // If the number isn't recognized as a valid value for this
+ // enum, drop it (don't even add it to unknownFields).
+ return true;
+ }
+ builder.addRepeatedField(field, value);
+ }
+ } else {
+ while (input.getBytesUntilLimit() > 0) {
+ final Object value =
+ FieldSet.readPrimitiveField(input, field.getLiteType());
+ builder.addRepeatedField(field, value);
+ }
+ }
+ input.popLimit(limit);
+ } else {
+ final Object value;
+ switch (field.getType()) {
+ case GROUP: {
+ final Message.Builder subBuilder;
+ if (defaultInstance != null) {
+ subBuilder = defaultInstance.newBuilderForType();
+ } else {
+ subBuilder = builder.newBuilderForField(field);
+ }
+ if (!field.isRepeated()) {
+ subBuilder.mergeFrom((Message) builder.getField(field));
+ }
+ input.readGroup(field.getNumber(), subBuilder, extensionRegistry);
+ value = subBuilder.build();
+ break;
+ }
+ case MESSAGE: {
+ final Message.Builder subBuilder;
+ if (defaultInstance != null) {
+ subBuilder = defaultInstance.newBuilderForType();
+ } else {
+ subBuilder = builder.newBuilderForField(field);
+ }
+ if (!field.isRepeated()) {
+ subBuilder.mergeFrom((Message) builder.getField(field));
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ value = subBuilder.build();
+ break;
+ }
+ case ENUM:
+ final int rawValue = input.readEnum();
+ value = field.getEnumType().findValueByNumber(rawValue);
+ // If the number isn't recognized as a valid value for this enum,
+ // drop it.
+ if (value == null) {
+ unknownFields.mergeVarintField(fieldNumber, rawValue);
+ return true;
+ }
+ break;
+ default:
+ value = FieldSet.readPrimitiveField(input, field.getLiteType());
+ break;
+ }
+
+ if (field.isRepeated()) {
+ builder.addRepeatedField(field, value);
+ } else {
+ builder.setField(field, value);
+ }
+ }
+
+ return true;
+ }
+
+ /** Called by {@code #mergeFieldFrom()} to parse a MessageSet extension. */
+ private static void mergeMessageSetExtensionFromCodedStream(
+ final CodedInputStream input,
+ final UnknownFieldSet.Builder unknownFields,
+ final ExtensionRegistryLite extensionRegistry,
+ final Message.Builder builder) throws IOException {
+ final Descriptor type = builder.getDescriptorForType();
+
+ // The wire format for MessageSet is:
+ // message MessageSet {
+ // repeated group Item = 1 {
+ // required int32 typeId = 2;
+ // required bytes message = 3;
+ // }
+ // }
+ // "typeId" is the extension's field number. The extension can only be
+ // a message type, where "message" contains the encoded bytes of that
+ // message.
+ //
+ // In practice, we will probably never see a MessageSet item in which
+ // the message appears before the type ID, or where either field does not
+ // appear exactly once. However, in theory such cases are valid, so we
+ // should be prepared to accept them.
+
+ int typeId = 0;
+ ByteString rawBytes = null; // If we encounter "message" before "typeId"
+ Message.Builder subBuilder = null;
+ FieldDescriptor field = null;
+
+ while (true) {
+ final int tag = input.readTag();
+ if (tag == 0) {
+ break;
+ }
+
+ if (tag == WireFormat.MESSAGE_SET_TYPE_ID_TAG) {
+ typeId = input.readUInt32();
+ // Zero is not a valid type ID.
+ if (typeId != 0) {
+ final ExtensionRegistry.ExtensionInfo extension;
+
+ // extensionRegistry may be either ExtensionRegistry or
+ // ExtensionRegistryLite. Since the type we are parsing is a full
+ // message, only a full ExtensionRegistry could possibly contain
+ // extensions of it. Otherwise we will treat the registry as if it
+ // were empty.
+ if (extensionRegistry instanceof ExtensionRegistry) {
+ extension = ((ExtensionRegistry) extensionRegistry)
+ .findExtensionByNumber(type, typeId);
+ } else {
+ extension = null;
+ }
+
+ if (extension != null) {
+ field = extension.descriptor;
+ subBuilder = extension.defaultInstance.newBuilderForType();
+ final Message originalMessage = (Message)builder.getField(field);
+ if (originalMessage != null) {
+ subBuilder.mergeFrom(originalMessage);
+ }
+ if (rawBytes != null) {
+ // We already encountered the message. Parse it now.
+ subBuilder.mergeFrom(
+ CodedInputStream.newInstance(rawBytes.newInput()));
+ rawBytes = null;
+ }
+ } else {
+ // Unknown extension number. If we already saw data, put it
+ // in rawBytes.
+ if (rawBytes != null) {
+ unknownFields.mergeField(typeId,
+ UnknownFieldSet.Field.newBuilder()
+ .addLengthDelimited(rawBytes)
+ .build());
+ rawBytes = null;
+ }
+ }
+ }
+ } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) {
+ if (typeId == 0) {
+ // We haven't seen a type ID yet, so we have to store the raw bytes
+ // for now.
+ rawBytes = input.readBytes();
+ } else if (subBuilder == null) {
+ // We don't know how to parse this. Ignore it.
+ unknownFields.mergeField(typeId,
+ UnknownFieldSet.Field.newBuilder()
+ .addLengthDelimited(input.readBytes())
+ .build());
+ } else {
+ // We already know the type, so we can parse directly from the input
+ // with no copying. Hooray!
+ input.readMessage(subBuilder, extensionRegistry);
+ }
+ } else {
+ // Unknown tag. Skip it.
+ if (!input.skipField(tag)) {
+ break; // end of group
+ }
+ }
+ }
+
+ input.checkLastTagWas(WireFormat.MESSAGE_SET_ITEM_END_TAG);
+
+ if (subBuilder != null) {
+ builder.setField(field, subBuilder.build());
+ }
+ }
+
+ public BuilderType mergeUnknownFields(final UnknownFieldSet unknownFields) {
setUnknownFields(
UnknownFieldSet.newBuilder(getUnknownFields())
.mergeFrom(unknownFields)
@@ -313,145 +522,169 @@ public abstract class AbstractMessage implements Message {
return (BuilderType) this;
}
- public BuilderType mergeFrom(ByteString data)
- throws InvalidProtocolBufferException {
- try {
- CodedInputStream input = data.newCodedInput();
- mergeFrom(input);
- input.checkLastTagWas(0);
- return (BuilderType) this;
- } catch (InvalidProtocolBufferException e) {
- throw e;
- } catch (IOException e) {
- throw new RuntimeException(
- "Reading from a ByteString threw an IOException (should " +
- "never happen).", e);
+ /**
+ * Construct an UninitializedMessageException reporting missing fields in
+ * the given message.
+ */
+ protected static UninitializedMessageException
+ newUninitializedMessageException(Message message) {
+ return new UninitializedMessageException(findMissingFields(message));
+ }
+
+ /**
+ * Populates {@code this.missingFields} with the full "path" of each
+ * missing required field in the given message.
+ */
+ private static List<String> findMissingFields(final Message message) {
+ final List<String> results = new ArrayList<String>();
+ findMissingFields(message, "", results);
+ return results;
+ }
+
+ /** Recursive helper implementing {@link #findMissingFields(Message)}. */
+ private static void findMissingFields(final Message message,
+ final String prefix,
+ final List<String> results) {
+ for (final FieldDescriptor field :
+ message.getDescriptorForType().getFields()) {
+ if (field.isRequired() && !message.hasField(field)) {
+ results.add(prefix + field.getName());
+ }
+ }
+
+ for (final Map.Entry<FieldDescriptor, Object> entry :
+ message.getAllFields().entrySet()) {
+ final FieldDescriptor field = entry.getKey();
+ final Object value = entry.getValue();
+
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ if (field.isRepeated()) {
+ int i = 0;
+ for (final Object element : (List) value) {
+ findMissingFields((Message) element,
+ subMessagePrefix(prefix, field, i++),
+ results);
+ }
+ } else {
+ if (message.hasField(field)) {
+ findMissingFields((Message) value,
+ subMessagePrefix(prefix, field, -1),
+ results);
+ }
+ }
+ }
}
}
- public BuilderType mergeFrom(ByteString data,
- ExtensionRegistry extensionRegistry)
- throws InvalidProtocolBufferException {
- try {
- CodedInputStream input = data.newCodedInput();
- mergeFrom(input, extensionRegistry);
- input.checkLastTagWas(0);
- return (BuilderType) this;
- } catch (InvalidProtocolBufferException e) {
- throw e;
- } catch (IOException e) {
- throw new RuntimeException(
- "Reading from a ByteString threw an IOException (should " +
- "never happen).", e);
+ private static String subMessagePrefix(final String prefix,
+ final FieldDescriptor field,
+ final int index) {
+ final StringBuilder result = new StringBuilder(prefix);
+ if (field.isExtension()) {
+ result.append('(')
+ .append(field.getFullName())
+ .append(')');
+ } else {
+ result.append(field.getName());
}
+ if (index != -1) {
+ result.append('[')
+ .append(index)
+ .append(']');
+ }
+ result.append('.');
+ return result.toString();
}
- public BuilderType mergeFrom(byte[] data)
+ // ===============================================================
+ // The following definitions seem to be required in order to make javac
+ // not produce weird errors like:
+ //
+ // java/com/google/protobuf/DynamicMessage.java:203: types
+ // com.google.protobuf.AbstractMessage.Builder<
+ // com.google.protobuf.DynamicMessage.Builder> and
+ // com.google.protobuf.AbstractMessage.Builder<
+ // com.google.protobuf.DynamicMessage.Builder> are incompatible; both
+ // define mergeFrom(com.google.protobuf.ByteString), but with unrelated
+ // return types.
+ //
+ // Strangely, these lines are only needed if javac is invoked separately
+ // on AbstractMessage.java and AbstractMessageLite.java. If javac is
+ // invoked on both simultaneously, it works. (Or maybe the important
+ // point is whether or not DynamicMessage.java is compiled together with
+ // AbstractMessageLite.java -- not sure.) I suspect this is a compiler
+ // bug.
+
+ @Override
+ public BuilderType mergeFrom(final ByteString data)
throws InvalidProtocolBufferException {
- return mergeFrom(data, 0, data.length);
+ return super.mergeFrom(data);
}
- public BuilderType mergeFrom(byte[] data, int off, int len)
+ @Override
+ public BuilderType mergeFrom(
+ final ByteString data,
+ final ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
- try {
- CodedInputStream input = CodedInputStream.newInstance(data, off, len);
- mergeFrom(input);
- input.checkLastTagWas(0);
- return (BuilderType) this;
- } catch (InvalidProtocolBufferException e) {
- throw e;
- } catch (IOException e) {
- throw new RuntimeException(
- "Reading from a byte array threw an IOException (should " +
- "never happen).", e);
- }
+ return super.mergeFrom(data, extensionRegistry);
}
- public BuilderType mergeFrom(
- byte[] data,
- ExtensionRegistry extensionRegistry)
+ @Override
+ public BuilderType mergeFrom(final byte[] data)
throws InvalidProtocolBufferException {
- return mergeFrom(data, 0, data.length, extensionRegistry);
+ return super.mergeFrom(data);
}
+ @Override
public BuilderType mergeFrom(
- byte[] data, int off, int len,
- ExtensionRegistry extensionRegistry)
+ final byte[] data, final int off, final int len)
throws InvalidProtocolBufferException {
- try {
- CodedInputStream input = CodedInputStream.newInstance(data, off, len);
- mergeFrom(input, extensionRegistry);
- input.checkLastTagWas(0);
- return (BuilderType) this;
- } catch (InvalidProtocolBufferException e) {
- throw e;
- } catch (IOException e) {
- throw new RuntimeException(
- "Reading from a byte array threw an IOException (should " +
- "never happen).", e);
- }
+ return super.mergeFrom(data, off, len);
}
- public BuilderType mergeFrom(InputStream input) throws IOException {
- CodedInputStream codedInput = CodedInputStream.newInstance(input);
- mergeFrom(codedInput);
- codedInput.checkLastTagWas(0);
- return (BuilderType) this;
+ @Override
+ public BuilderType mergeFrom(
+ final byte[] data,
+ final ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return super.mergeFrom(data, extensionRegistry);
}
- public BuilderType mergeFrom(InputStream input,
- ExtensionRegistry extensionRegistry)
- throws IOException {
- CodedInputStream codedInput = CodedInputStream.newInstance(input);
- mergeFrom(codedInput, extensionRegistry);
- codedInput.checkLastTagWas(0);
- return (BuilderType) this;
+ @Override
+ public BuilderType mergeFrom(
+ final byte[] data, final int off, final int len,
+ final ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return super.mergeFrom(data, off, len, extensionRegistry);
}
- public BuilderType mergeDelimitedFrom(InputStream input,
- ExtensionRegistry extensionRegistry)
- throws IOException {
- final int size = CodedInputStream.readRawVarint32(input);
-
- // A stream which will not read more than |size| bytes.
- InputStream limitedInput = new FilterInputStream(input) {
- int limit = size;
-
- @Override
- public int available() throws IOException {
- return Math.min(super.available(), limit);
- }
-
- @Override
- public int read() throws IOException {
- if (limit <= 0) return -1;
- int result = super.read();
- if (result >= 0) --limit;
- return result;
- }
+ @Override
+ public BuilderType mergeFrom(final InputStream input)
+ throws IOException {
+ return super.mergeFrom(input);
+ }
- @Override
- public int read(byte[] b, int off, int len) throws IOException {
- if (limit <= 0) return -1;
- len = Math.min(len, limit);
- int result = super.read(b, off, len);
- if (result >= 0) limit -= result;
- return result;
- }
+ @Override
+ public BuilderType mergeFrom(
+ final InputStream input,
+ final ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ return super.mergeFrom(input, extensionRegistry);
+ }
- @Override
- public long skip(long n) throws IOException {
- long result = super.skip(Math.min(n, limit));
- if (result >= 0) limit -= result;
- return result;
- }
- };
- return mergeFrom(limitedInput, extensionRegistry);
+ @Override
+ public BuilderType mergeDelimitedFrom(final InputStream input)
+ throws IOException {
+ return super.mergeDelimitedFrom(input);
}
- public BuilderType mergeDelimitedFrom(InputStream input)
+ @Override
+ public BuilderType mergeDelimitedFrom(
+ final InputStream input,
+ final ExtensionRegistryLite extensionRegistry)
throws IOException {
- return mergeDelimitedFrom(input, ExtensionRegistry.getEmptyRegistry());
+ return super.mergeDelimitedFrom(input, extensionRegistry);
}
+
}
}
diff --git a/java/src/main/java/com/google/protobuf/AbstractMessageLite.java b/java/src/main/java/com/google/protobuf/AbstractMessageLite.java
new file mode 100644
index 00000000..489577df
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/AbstractMessageLite.java
@@ -0,0 +1,321 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import java.io.FilterInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Collection;
+
+/**
+ * A partial implementation of the {@link MessageLite} interface which
+ * implements as many methods of that interface as possible in terms of other
+ * methods.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public abstract class AbstractMessageLite implements MessageLite {
+ public ByteString toByteString() {
+ try {
+ final ByteString.CodedBuilder out =
+ ByteString.newCodedBuilder(getSerializedSize());
+ writeTo(out.getCodedOutput());
+ return out.build();
+ } catch (IOException e) {
+ throw new RuntimeException(
+ "Serializing to a ByteString threw an IOException (should " +
+ "never happen).", e);
+ }
+ }
+
+ public byte[] toByteArray() {
+ try {
+ final byte[] result = new byte[getSerializedSize()];
+ final CodedOutputStream output = CodedOutputStream.newInstance(result);
+ writeTo(output);
+ output.checkNoSpaceLeft();
+ return result;
+ } catch (IOException e) {
+ throw new RuntimeException(
+ "Serializing to a byte array threw an IOException " +
+ "(should never happen).", e);
+ }
+ }
+
+ public void writeTo(final OutputStream output) throws IOException {
+ final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
+ writeTo(codedOutput);
+ codedOutput.flush();
+ }
+
+ public void writeDelimitedTo(final OutputStream output) throws IOException {
+ final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
+ codedOutput.writeRawVarint32(getSerializedSize());
+ writeTo(codedOutput);
+ codedOutput.flush();
+ }
+
+ /**
+ * A partial implementation of the {@link Message.Builder} interface which
+ * implements as many methods of that interface as possible in terms of
+ * other methods.
+ */
+ @SuppressWarnings("unchecked")
+ public static abstract class Builder<BuilderType extends Builder>
+ 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 {
+ // TODO(kenton): Don't use null here. Currently we have to because
+ // using ExtensionRegistry.getEmptyRegistry() would imply a dependency
+ // on ExtensionRegistry. However, AbstractMessage overrides this with
+ // a correct implementation, and lite messages don't yet support
+ // extensions, so it ends up not mattering for now. It will matter
+ // once lite messages support extensions.
+ return mergeFrom(input, null);
+ }
+
+ // Re-defined here for return type covariance.
+ public abstract BuilderType mergeFrom(
+ final CodedInputStream input,
+ final ExtensionRegistryLite extensionRegistry)
+ throws IOException;
+
+ public BuilderType mergeFrom(final ByteString data)
+ throws InvalidProtocolBufferException {
+ try {
+ final CodedInputStream input = data.newCodedInput();
+ mergeFrom(input);
+ input.checkLastTagWas(0);
+ return (BuilderType) this;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new RuntimeException(
+ "Reading from a ByteString threw an IOException (should " +
+ "never happen).", e);
+ }
+ }
+
+ public BuilderType mergeFrom(
+ final ByteString data,
+ final ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ try {
+ final CodedInputStream input = data.newCodedInput();
+ mergeFrom(input, extensionRegistry);
+ input.checkLastTagWas(0);
+ return (BuilderType) this;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new RuntimeException(
+ "Reading from a ByteString threw an IOException (should " +
+ "never happen).", e);
+ }
+ }
+
+ 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 {
+ try {
+ final CodedInputStream input =
+ CodedInputStream.newInstance(data, off, len);
+ mergeFrom(input);
+ input.checkLastTagWas(0);
+ return (BuilderType) this;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new RuntimeException(
+ "Reading from a byte array threw an IOException (should " +
+ "never happen).", e);
+ }
+ }
+
+ public BuilderType mergeFrom(
+ final byte[] data,
+ final ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return mergeFrom(data, 0, data.length, extensionRegistry);
+ }
+
+ public BuilderType mergeFrom(
+ final byte[] data, final int off, final int len,
+ final ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ try {
+ final CodedInputStream input =
+ CodedInputStream.newInstance(data, off, len);
+ mergeFrom(input, extensionRegistry);
+ input.checkLastTagWas(0);
+ return (BuilderType) this;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new RuntimeException(
+ "Reading from a byte array threw an IOException (should " +
+ "never happen).", e);
+ }
+ }
+
+ public BuilderType mergeFrom(final InputStream input) throws IOException {
+ final CodedInputStream codedInput = CodedInputStream.newInstance(input);
+ mergeFrom(codedInput);
+ codedInput.checkLastTagWas(0);
+ return (BuilderType) this;
+ }
+
+ public BuilderType mergeFrom(
+ final InputStream input,
+ final ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ final CodedInputStream codedInput = CodedInputStream.newInstance(input);
+ mergeFrom(codedInput, extensionRegistry);
+ codedInput.checkLastTagWas(0);
+ return (BuilderType) this;
+ }
+
+ /**
+ * An InputStream implementations which reads from some other InputStream
+ * but is limited to a particular number of bytes. Used by
+ * mergeDelimitedFrom(). This is intentionally package-private so that
+ * UnknownFieldSet can share it.
+ */
+ static final class LimitedInputStream extends FilterInputStream {
+ private int limit;
+
+ LimitedInputStream(InputStream in, int limit) {
+ super(in);
+ this.limit = limit;
+ }
+
+ @Override
+ public int available() throws IOException {
+ return Math.min(super.available(), limit);
+ }
+
+ @Override
+ public int read() throws IOException {
+ if (limit <= 0) {
+ return -1;
+ }
+ final int result = super.read();
+ if (result >= 0) {
+ --limit;
+ }
+ return result;
+ }
+
+ @Override
+ public int read(final byte[] b, final int off, int len)
+ throws IOException {
+ if (limit <= 0) {
+ return -1;
+ }
+ len = Math.min(len, limit);
+ final int result = super.read(b, off, len);
+ if (result >= 0) {
+ limit -= result;
+ }
+ return result;
+ }
+
+ @Override
+ public long skip(final long n) throws IOException {
+ final long result = super.skip(Math.min(n, limit));
+ if (result >= 0) {
+ limit -= result;
+ }
+ return result;
+ }
+ }
+
+ public BuilderType mergeDelimitedFrom(
+ final InputStream input,
+ final ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ final int size = CodedInputStream.readRawVarint32(input);
+ final InputStream limitedInput = new LimitedInputStream(input, size);
+ return mergeFrom(limitedInput, extensionRegistry);
+ }
+
+ public BuilderType mergeDelimitedFrom(final InputStream input)
+ throws IOException {
+ final int size = CodedInputStream.readRawVarint32(input);
+ final InputStream limitedInput = new LimitedInputStream(input, size);
+ return mergeFrom(limitedInput);
+ }
+
+ /**
+ * Construct an UninitializedMessageException reporting missing fields in
+ * the given message.
+ */
+ protected static UninitializedMessageException
+ newUninitializedMessageException(MessageLite message) {
+ return new UninitializedMessageException(message);
+ }
+
+ /**
+ * Adds the {@code values} to the {@code list}. This is a helper method
+ * used by generated code. Users should ignore it.
+ *
+ * @throws NullPointerException if any of the elements of {@code values} is
+ * null.
+ */
+ protected static <T> void addAll(final Iterable<T> values,
+ final Collection<? super T> list) {
+ for (final T value : values) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ }
+ if (values instanceof Collection) {
+ @SuppressWarnings("unsafe") final
+ Collection<T> collection = (Collection<T>) values;
+ list.addAll(collection);
+ } else {
+ for (final T value : values) {
+ list.add(value);
+ }
+ }
+ }
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/ByteString.java b/java/src/main/java/com/google/protobuf/ByteString.java
index f376e7a1..c83c335c 100644
--- a/java/src/main/java/com/google/protobuf/ByteString.java
+++ b/java/src/main/java/com/google/protobuf/ByteString.java
@@ -46,7 +46,7 @@ import java.nio.ByteBuffer;
public final class ByteString {
private final byte[] bytes;
- private ByteString(byte[] bytes) {
+ private ByteString(final byte[] bytes) {
this.bytes = bytes;
}
@@ -55,7 +55,7 @@ public final class ByteString {
*
* @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size
*/
- public byte byteAt(int index) {
+ public byte byteAt(final int index) {
return bytes[index];
}
@@ -63,14 +63,14 @@ public final class ByteString {
* Gets the number of bytes.
*/
public int size() {
- return this.bytes.length;
+ return bytes.length;
}
/**
* Returns {@code true} if the size is {@code 0}, {@code false} otherwise.
*/
public boolean isEmpty() {
- return this.bytes.length == 0;
+ return bytes.length == 0;
}
// =================================================================
@@ -84,8 +84,9 @@ public final class ByteString {
/**
* Copies the given bytes into a {@code ByteString}.
*/
- public static ByteString copyFrom(byte[] bytes, int offset, int size) {
- byte[] copy = new byte[size];
+ public static ByteString copyFrom(final byte[] bytes, final int offset,
+ final int size) {
+ final byte[] copy = new byte[size];
System.arraycopy(bytes, offset, copy, 0, size);
return new ByteString(copy);
}
@@ -93,7 +94,7 @@ public final class ByteString {
/**
* Copies the given bytes into a {@code ByteString}.
*/
- public static ByteString copyFrom(byte[] bytes) {
+ public static ByteString copyFrom(final byte[] bytes) {
return copyFrom(bytes, 0, bytes.length);
}
@@ -101,7 +102,7 @@ public final class ByteString {
* Encodes {@code text} into a sequence of bytes using the named charset
* and returns the result as a {@code ByteString}.
*/
- public static ByteString copyFrom(String text, String charsetName)
+ public static ByteString copyFrom(final String text, final String charsetName)
throws UnsupportedEncodingException {
return new ByteString(text.getBytes(charsetName));
}
@@ -110,7 +111,7 @@ public final class ByteString {
* Encodes {@code text} into a sequence of UTF-8 bytes and returns the
* result as a {@code ByteString}.
*/
- public static ByteString copyFromUtf8(String text) {
+ public static ByteString copyFromUtf8(final String text) {
try {
return new ByteString(text.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
@@ -127,7 +128,7 @@ public final class ByteString {
* @param target buffer to copy into
* @param offset in the target buffer
*/
- public void copyTo(byte[] target, int offset) {
+ public void copyTo(final byte[] target, final int offset) {
System.arraycopy(bytes, 0, target, offset, bytes.length);
}
@@ -139,8 +140,9 @@ public final class ByteString {
* @param targetOffset offset within the target buffer
* @param size number of bytes to copy
*/
- public void copyTo(byte[] target, int sourceOffset, int targetOffset,
- int size) {
+ public void copyTo(final byte[] target, final int sourceOffset,
+ final int targetOffset,
+ final int size) {
System.arraycopy(bytes, sourceOffset, target, targetOffset, size);
}
@@ -148,9 +150,9 @@ public final class ByteString {
* Copies bytes to a {@code byte[]}.
*/
public byte[] toByteArray() {
- int size = this.bytes.length;
- byte[] copy = new byte[size];
- System.arraycopy(this.bytes, 0, copy, 0, size);
+ final int size = bytes.length;
+ final byte[] copy = new byte[size];
+ System.arraycopy(bytes, 0, copy, 0, size);
return copy;
}
@@ -159,7 +161,7 @@ public final class ByteString {
* same backing byte array.
*/
public ByteBuffer asReadOnlyByteBuffer() {
- ByteBuffer byteBuffer = ByteBuffer.wrap(this.bytes);
+ final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
return byteBuffer.asReadOnlyBuffer();
}
@@ -167,9 +169,9 @@ public final class ByteString {
* Constructs a new {@code String} by decoding the bytes using the
* specified charset.
*/
- public String toString(String charsetName)
+ public String toString(final String charsetName)
throws UnsupportedEncodingException {
- return new String(this.bytes, charsetName);
+ return new String(bytes, charsetName);
}
/**
@@ -177,7 +179,7 @@ public final class ByteString {
*/
public String toStringUtf8() {
try {
- return new String(this.bytes, "UTF-8");
+ return new String(bytes, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("UTF-8 not supported?", e);
}
@@ -187,7 +189,7 @@ public final class ByteString {
// equals() and hashCode()
@Override
- public boolean equals(Object o) {
+ public boolean equals(final Object o) {
if (o == this) {
return true;
}
@@ -196,16 +198,16 @@ public final class ByteString {
return false;
}
- ByteString other = (ByteString) o;
- int size = this.bytes.length;
+ final ByteString other = (ByteString) o;
+ final int size = bytes.length;
if (size != other.bytes.length) {
return false;
}
- byte[] bytes = this.bytes;
- byte[] otherBytes = other.bytes;
+ final byte[] thisBytes = bytes;
+ final byte[] otherBytes = other.bytes;
for (int i = 0; i < size; i++) {
- if (bytes[i] != otherBytes[i]) {
+ if (thisBytes[i] != otherBytes[i]) {
return false;
}
}
@@ -213,25 +215,25 @@ public final class ByteString {
return true;
}
- volatile int hash = 0;
+ private volatile int hash = 0;
@Override
public int hashCode() {
- int h = this.hash;
+ int h = hash;
if (h == 0) {
- byte[] bytes = this.bytes;
- int size = this.bytes.length;
+ final byte[] thisBytes = bytes;
+ final int size = bytes.length;
h = size;
for (int i = 0; i < size; i++) {
- h = h * 31 + bytes[i];
+ h = h * 31 + thisBytes[i];
}
if (h == 0) {
h = 1;
}
- this.hash = h;
+ hash = h;
}
return h;
@@ -264,7 +266,7 @@ public final class ByteString {
/**
* Creates a new {@link Output} with the given initial capacity.
*/
- public static Output newOutput(int initialCapacity) {
+ public static Output newOutput(final int initialCapacity) {
return new Output(new ByteArrayOutputStream(initialCapacity));
}
@@ -285,7 +287,7 @@ public final class ByteString {
/**
* Constructs a new output with the given initial capacity.
*/
- private Output(ByteArrayOutputStream bout) {
+ private Output(final ByteArrayOutputStream bout) {
super(bout);
this.bout = bout;
}
@@ -294,14 +296,14 @@ public final class ByteString {
* Creates a {@code ByteString} instance from this {@code Output}.
*/
public ByteString toByteString() {
- byte[] byteArray = bout.toByteArray();
+ final byte[] byteArray = bout.toByteArray();
return new ByteString(byteArray);
}
}
/**
* Constructs a new ByteString builder, which allows you to efficiently
- * construct a {@code ByteString} by writing to a {@link CodedOutputSteam}.
+ * construct a {@code ByteString} by writing to a {@link CodedOutputStream}.
* Using this is much more efficient than calling {@code newOutput()} and
* wrapping that in a {@code CodedOutputStream}.
*
@@ -312,7 +314,7 @@ public final class ByteString {
* @param size The target byte size of the {@code ByteString}. You must
* write exactly this many bytes before building the result.
*/
- static CodedBuilder newCodedBuilder(int size) {
+ static CodedBuilder newCodedBuilder(final int size) {
return new CodedBuilder(size);
}
@@ -321,7 +323,7 @@ public final class ByteString {
private final CodedOutputStream output;
private final byte[] buffer;
- private CodedBuilder(int size) {
+ private CodedBuilder(final int size) {
buffer = new byte[size];
output = CodedOutputStream.newInstance(buffer);
}
diff --git a/java/src/main/java/com/google/protobuf/CodedInputStream.java b/java/src/main/java/com/google/protobuf/CodedInputStream.java
index b6be2e87..9125957d 100644
--- a/java/src/main/java/com/google/protobuf/CodedInputStream.java
+++ b/java/src/main/java/com/google/protobuf/CodedInputStream.java
@@ -51,21 +51,22 @@ public final class CodedInputStream {
/**
* Create a new CodedInputStream wrapping the given InputStream.
*/
- public static CodedInputStream newInstance(InputStream input) {
+ public static CodedInputStream newInstance(final InputStream input) {
return new CodedInputStream(input);
}
/**
* Create a new CodedInputStream wrapping the given byte array.
*/
- public static CodedInputStream newInstance(byte[] buf) {
+ public static CodedInputStream newInstance(final byte[] buf) {
return newInstance(buf, 0, buf.length);
}
/**
* Create a new CodedInputStream wrapping the given byte array slice.
*/
- public static CodedInputStream newInstance(byte[] buf, int off, int len) {
+ public static CodedInputStream newInstance(final byte[] buf, final int off,
+ final int len) {
return new CodedInputStream(buf, off, len);
}
@@ -98,7 +99,8 @@ public final class CodedInputStream {
* @throws InvalidProtocolBufferException {@code value} does not match the
* last tag.
*/
- public void checkLastTagWas(int value) throws InvalidProtocolBufferException {
+ public void checkLastTagWas(final int value)
+ throws InvalidProtocolBufferException {
if (lastTag != value) {
throw InvalidProtocolBufferException.invalidEndTag();
}
@@ -110,7 +112,7 @@ public final class CodedInputStream {
* @return {@code false} if the tag is an endgroup tag, in which case
* nothing is skipped. Otherwise, returns {@code true}.
*/
- public boolean skipField(int tag) throws IOException {
+ public boolean skipField(final int tag) throws IOException {
switch (WireFormat.getTagWireType(tag)) {
case WireFormat.WIRETYPE_VARINT:
readInt32();
@@ -143,8 +145,10 @@ public final class CodedInputStream {
*/
public void skipMessage() throws IOException {
while (true) {
- int tag = readTag();
- if (tag == 0 || !skipField(tag)) return;
+ final int tag = readTag();
+ if (tag == 0 || !skipField(tag)) {
+ return;
+ }
}
}
@@ -192,11 +196,11 @@ public final class CodedInputStream {
/** Read a {@code string} field value from the stream. */
public String readString() throws IOException {
- int size = readRawVarint32();
+ final int size = readRawVarint32();
if (size <= (bufferSize - bufferPos) && size > 0) {
// Fast path: We already have the bytes in a contiguous buffer, so
// just copy directly from it.
- String result = new String(buffer, bufferPos, size, "UTF-8");
+ final String result = new String(buffer, bufferPos, size, "UTF-8");
bufferPos += size;
return result;
} else {
@@ -206,8 +210,9 @@ public final class CodedInputStream {
}
/** Read a {@code group} field value from the stream. */
- public void readGroup(int fieldNumber, Message.Builder builder,
- ExtensionRegistry extensionRegistry)
+ public void readGroup(final int fieldNumber,
+ final MessageLite.Builder builder,
+ final ExtensionRegistryLite extensionRegistry)
throws IOException {
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.recursionLimitExceeded();
@@ -222,28 +227,31 @@ public final class CodedInputStream {
/**
* Reads a {@code group} field value from the stream and merges it into the
* given {@link UnknownFieldSet}.
+ *
+ * @deprecated UnknownFieldSet.Builder now implements MessageLite.Builder, so
+ * you can just call {@link #readGroup}.
*/
- public void readUnknownGroup(int fieldNumber, UnknownFieldSet.Builder builder)
+ @Deprecated
+ public void readUnknownGroup(final int fieldNumber,
+ final MessageLite.Builder builder)
throws IOException {
- if (recursionDepth >= recursionLimit) {
- throw InvalidProtocolBufferException.recursionLimitExceeded();
- }
- ++recursionDepth;
- builder.mergeFrom(this);
- checkLastTagWas(
- WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
- --recursionDepth;
+ // We know that UnknownFieldSet will ignore any ExtensionRegistry so it
+ // is safe to pass null here. (We can't call
+ // ExtensionRegistry.getEmptyRegistry() because that would make this
+ // class depend on ExtensionRegistry, which is not part of the lite
+ // library.)
+ readGroup(fieldNumber, builder, null);
}
/** Read an embedded message field value from the stream. */
- public void readMessage(Message.Builder builder,
- ExtensionRegistry extensionRegistry)
+ public void readMessage(final MessageLite.Builder builder,
+ final ExtensionRegistryLite extensionRegistry)
throws IOException {
- int length = readRawVarint32();
+ final int length = readRawVarint32();
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.recursionLimitExceeded();
}
- int oldLimit = pushLimit(length);
+ final int oldLimit = pushLimit(length);
++recursionDepth;
builder.mergeFrom(this, extensionRegistry);
checkLastTagWas(0);
@@ -253,11 +261,11 @@ public final class CodedInputStream {
/** Read a {@code bytes} field value from the stream. */
public ByteString readBytes() throws IOException {
- int size = readRawVarint32();
- if (size < bufferSize - bufferPos && size > 0) {
+ final int size = readRawVarint32();
+ if (size <= (bufferSize - bufferPos) && size > 0) {
// Fast path: We already have the bytes in a contiguous buffer, so
// just copy directly from it.
- ByteString result = ByteString.copyFrom(buffer, bufferPos, size);
+ final ByteString result = ByteString.copyFrom(buffer, bufferPos, size);
bufferPos += size;
return result;
} else {
@@ -299,52 +307,6 @@ public final class CodedInputStream {
return decodeZigZag64(readRawVarint64());
}
- /**
- * Read a field of any primitive type. Enums, groups, and embedded
- * messages are not handled by this method.
- *
- * @param type Declared type of the field.
- * @return An object representing the field's value, of the exact
- * type which would be returned by
- * {@link Message#getField(Descriptors.FieldDescriptor)} for
- * this field.
- */
- public Object readPrimitiveField(
- Descriptors.FieldDescriptor.Type type) throws IOException {
- switch (type) {
- case DOUBLE : return readDouble ();
- case FLOAT : return readFloat ();
- case INT64 : return readInt64 ();
- case UINT64 : return readUInt64 ();
- case INT32 : return readInt32 ();
- case FIXED64 : return readFixed64 ();
- case FIXED32 : return readFixed32 ();
- case BOOL : return readBool ();
- case STRING : return readString ();
- case BYTES : return readBytes ();
- case UINT32 : return readUInt32 ();
- case SFIXED32: return readSFixed32();
- case SFIXED64: return readSFixed64();
- case SINT32 : return readSInt32 ();
- case SINT64 : return readSInt64 ();
-
- case GROUP:
- throw new IllegalArgumentException(
- "readPrimitiveField() cannot handle nested groups.");
- case MESSAGE:
- throw new IllegalArgumentException(
- "readPrimitiveField() cannot handle embedded messages.");
- case ENUM:
- // We don't hanlde enums because we don't know what to do if the
- // value is not recognized.
- throw new IllegalArgumentException(
- "readPrimitiveField() cannot handle enums.");
- }
-
- throw new RuntimeException(
- "There is no way to get here, but the compiler thinks otherwise.");
- }
-
// =================================================================
/**
@@ -373,7 +335,9 @@ public final class CodedInputStream {
if (tmp < 0) {
// Discard upper 32 bits.
for (int i = 0; i < 5; i++) {
- if (readRawByte() >= 0) return result;
+ if (readRawByte() >= 0) {
+ return result;
+ }
}
throw InvalidProtocolBufferException.malformedVarint();
}
@@ -390,11 +354,11 @@ public final class CodedInputStream {
* then you would probably end up reading past the end of the varint since
* CodedInputStream buffers its input.
*/
- static int readRawVarint32(InputStream input) throws IOException {
+ static int readRawVarint32(final InputStream input) throws IOException {
int result = 0;
int offset = 0;
for (; offset < 32; offset += 7) {
- int b = input.read();
+ final int b = input.read();
if (b == -1) {
throw InvalidProtocolBufferException.truncatedMessage();
}
@@ -405,7 +369,7 @@ public final class CodedInputStream {
}
// Keep reading up to 64 bits.
for (; offset < 64; offset += 7) {
- int b = input.read();
+ final int b = input.read();
if (b == -1) {
throw InvalidProtocolBufferException.truncatedMessage();
}
@@ -421,9 +385,11 @@ public final class CodedInputStream {
int shift = 0;
long result = 0;
while (shift < 64) {
- byte b = readRawByte();
+ final byte b = readRawByte();
result |= (long)(b & 0x7F) << shift;
- if ((b & 0x80) == 0) return result;
+ if ((b & 0x80) == 0) {
+ return result;
+ }
shift += 7;
}
throw InvalidProtocolBufferException.malformedVarint();
@@ -431,10 +397,10 @@ public final class CodedInputStream {
/** Read a 32-bit little-endian integer from the stream. */
public int readRawLittleEndian32() throws IOException {
- byte b1 = readRawByte();
- byte b2 = readRawByte();
- byte b3 = readRawByte();
- byte b4 = readRawByte();
+ final byte b1 = readRawByte();
+ final byte b2 = readRawByte();
+ final byte b3 = readRawByte();
+ final byte b4 = readRawByte();
return (((int)b1 & 0xff) ) |
(((int)b2 & 0xff) << 8) |
(((int)b3 & 0xff) << 16) |
@@ -443,14 +409,14 @@ public final class CodedInputStream {
/** Read a 64-bit little-endian integer from the stream. */
public long readRawLittleEndian64() throws IOException {
- byte b1 = readRawByte();
- byte b2 = readRawByte();
- byte b3 = readRawByte();
- byte b4 = readRawByte();
- byte b5 = readRawByte();
- byte b6 = readRawByte();
- byte b7 = readRawByte();
- byte b8 = readRawByte();
+ final byte b1 = readRawByte();
+ final byte b2 = readRawByte();
+ final byte b3 = readRawByte();
+ final byte b4 = readRawByte();
+ final byte b5 = readRawByte();
+ final byte b6 = readRawByte();
+ final byte b7 = readRawByte();
+ final byte b8 = readRawByte();
return (((long)b1 & 0xff) ) |
(((long)b2 & 0xff) << 8) |
(((long)b3 & 0xff) << 16) |
@@ -471,7 +437,7 @@ public final class CodedInputStream {
* Java has no explicit unsigned support.
* @return A signed 32-bit integer.
*/
- public static int decodeZigZag32(int n) {
+ public static int decodeZigZag32(final int n) {
return (n >>> 1) ^ -(n & 1);
}
@@ -485,31 +451,31 @@ public final class CodedInputStream {
* Java has no explicit unsigned support.
* @return A signed 64-bit integer.
*/
- public static long decodeZigZag64(long n) {
+ public static long decodeZigZag64(final long n) {
return (n >>> 1) ^ -(n & 1);
}
// -----------------------------------------------------------------
- private byte[] buffer;
+ private final byte[] buffer;
private int bufferSize;
- private int bufferSizeAfterLimit = 0;
+ private int bufferSizeAfterLimit;
private int bufferPos;
- private InputStream input;
- private int lastTag = 0;
+ private final InputStream input;
+ private int lastTag;
/**
* The total number of bytes read before the current buffer. The total
* bytes read up to the current position can be computed as
* {@code totalBytesRetired + bufferPos}.
*/
- private int totalBytesRetired = 0;
+ private int totalBytesRetired;
/** The absolute position of the end of the current message. */
private int currentLimit = Integer.MAX_VALUE;
/** See setRecursionLimit() */
- private int recursionDepth = 0;
+ private int recursionDepth;
private int recursionLimit = DEFAULT_RECURSION_LIMIT;
/** See setSizeLimit() */
@@ -519,17 +485,17 @@ public final class CodedInputStream {
private static final int DEFAULT_SIZE_LIMIT = 64 << 20; // 64MB
private static final int BUFFER_SIZE = 4096;
- private CodedInputStream(byte[] buffer, int off, int len) {
+ private CodedInputStream(final byte[] buffer, final int off, final int len) {
this.buffer = buffer;
- this.bufferSize = off + len;
- this.bufferPos = off;
- this.input = null;
+ bufferSize = off + len;
+ bufferPos = off;
+ input = null;
}
- private CodedInputStream(InputStream input) {
- this.buffer = new byte[BUFFER_SIZE];
- this.bufferSize = 0;
- this.bufferPos = 0;
+ private CodedInputStream(final InputStream input) {
+ buffer = new byte[BUFFER_SIZE];
+ bufferSize = 0;
+ bufferPos = 0;
this.input = input;
}
@@ -540,12 +506,12 @@ public final class CodedInputStream {
*
* @return the old limit.
*/
- public int setRecursionLimit(int limit) {
+ public int setRecursionLimit(final int limit) {
if (limit < 0) {
throw new IllegalArgumentException(
"Recursion limit cannot be negative: " + limit);
}
- int oldLimit = recursionLimit;
+ final int oldLimit = recursionLimit;
recursionLimit = limit;
return oldLimit;
}
@@ -566,12 +532,12 @@ public final class CodedInputStream {
*
* @return the old limit.
*/
- public int setSizeLimit(int limit) {
+ public int setSizeLimit(final int limit) {
if (limit < 0) {
throw new IllegalArgumentException(
"Size limit cannot be negative: " + limit);
}
- int oldLimit = sizeLimit;
+ final int oldLimit = sizeLimit;
sizeLimit = limit;
return oldLimit;
}
@@ -594,7 +560,7 @@ public final class CodedInputStream {
throw InvalidProtocolBufferException.negativeSize();
}
byteLimit += totalBytesRetired + bufferPos;
- int oldLimit = currentLimit;
+ final int oldLimit = currentLimit;
if (byteLimit > oldLimit) {
throw InvalidProtocolBufferException.truncatedMessage();
}
@@ -607,7 +573,7 @@ public final class CodedInputStream {
private void recomputeBufferSizeAfterLimit() {
bufferSize += bufferSizeAfterLimit;
- int bufferEnd = totalBytesRetired + bufferSize;
+ final int bufferEnd = totalBytesRetired + bufferSize;
if (bufferEnd > currentLimit) {
// Limit is in current buffer.
bufferSizeAfterLimit = bufferEnd - currentLimit;
@@ -622,7 +588,7 @@ public final class CodedInputStream {
*
* @param oldLimit The old limit, as returned by {@code pushLimit}.
*/
- public void popLimit(int oldLimit) {
+ public void popLimit(final int oldLimit) {
currentLimit = oldLimit;
recomputeBufferSizeAfterLimit();
}
@@ -636,7 +602,7 @@ public final class CodedInputStream {
return -1;
}
- int currentAbsolutePosition = totalBytesRetired + bufferPos;
+ final int currentAbsolutePosition = totalBytesRetired + bufferPos;
return currentLimit - currentAbsolutePosition;
}
@@ -656,7 +622,7 @@ public final class CodedInputStream {
* or it will throw an exception. If {@code mustSucceed} is false,
* refillBuffer() returns false if no more bytes were available.
*/
- private boolean refillBuffer(boolean mustSucceed) throws IOException {
+ private boolean refillBuffer(final boolean mustSucceed) throws IOException {
if (bufferPos < bufferSize) {
throw new IllegalStateException(
"refillBuffer() called when buffer wasn't empty.");
@@ -689,7 +655,7 @@ public final class CodedInputStream {
}
} else {
recomputeBufferSizeAfterLimit();
- int totalBytesRead =
+ final int totalBytesRead =
totalBytesRetired + bufferSize + bufferSizeAfterLimit;
if (totalBytesRead > sizeLimit || totalBytesRead < 0) {
throw InvalidProtocolBufferException.sizeLimitExceeded();
@@ -717,7 +683,7 @@ public final class CodedInputStream {
* @throws InvalidProtocolBufferException The end of the stream or the current
* limit was reached.
*/
- public byte[] readRawBytes(int size) throws IOException {
+ public byte[] readRawBytes(final int size) throws IOException {
if (size < 0) {
throw InvalidProtocolBufferException.negativeSize();
}
@@ -731,7 +697,7 @@ public final class CodedInputStream {
if (size <= bufferSize - bufferPos) {
// We have all the bytes we need already.
- byte[] bytes = new byte[size];
+ final byte[] bytes = new byte[size];
System.arraycopy(buffer, bufferPos, bytes, 0, size);
bufferPos += size;
return bytes;
@@ -740,7 +706,7 @@ public final class CodedInputStream {
// of bytes. We can safely allocate the resulting array ahead of time.
// First copy what we have.
- byte[] bytes = new byte[size];
+ final byte[] bytes = new byte[size];
int pos = bufferSize - bufferPos;
System.arraycopy(buffer, bufferPos, bytes, 0, pos);
bufferPos = bufferSize;
@@ -772,8 +738,8 @@ public final class CodedInputStream {
// Remember the buffer markers since we'll have to copy the bytes out of
// it later.
- int originalBufferPos = bufferPos;
- int originalBufferSize = bufferSize;
+ final int originalBufferPos = bufferPos;
+ final int originalBufferSize = bufferSize;
// Mark the current buffer consumed.
totalBytesRetired += bufferSize;
@@ -782,13 +748,13 @@ public final class CodedInputStream {
// Read all the rest of the bytes we need.
int sizeLeft = size - (originalBufferSize - originalBufferPos);
- List<byte[]> chunks = new ArrayList<byte[]>();
+ final List<byte[]> chunks = new ArrayList<byte[]>();
while (sizeLeft > 0) {
- byte[] chunk = new byte[Math.min(sizeLeft, BUFFER_SIZE)];
+ final byte[] chunk = new byte[Math.min(sizeLeft, BUFFER_SIZE)];
int pos = 0;
while (pos < chunk.length) {
- int n = (input == null) ? -1 :
+ final int n = (input == null) ? -1 :
input.read(chunk, pos, chunk.length - pos);
if (n == -1) {
throw InvalidProtocolBufferException.truncatedMessage();
@@ -801,14 +767,14 @@ public final class CodedInputStream {
}
// OK, got everything. Now concatenate it all into one buffer.
- byte[] bytes = new byte[size];
+ final byte[] bytes = new byte[size];
// Start by copying the leftover bytes from this.buffer.
int pos = originalBufferSize - originalBufferPos;
System.arraycopy(buffer, originalBufferPos, bytes, 0, pos);
// And now all the chunks.
- for (byte[] chunk : chunks) {
+ for (final byte[] chunk : chunks) {
System.arraycopy(chunk, 0, bytes, pos, chunk.length);
pos += chunk.length;
}
@@ -824,7 +790,7 @@ public final class CodedInputStream {
* @throws InvalidProtocolBufferException The end of the stream or the current
* limit was reached.
*/
- public void skipRawBytes(int size) throws IOException {
+ public void skipRawBytes(final int size) throws IOException {
if (size < 0) {
throw InvalidProtocolBufferException.negativeSize();
}
@@ -848,7 +814,7 @@ public final class CodedInputStream {
// Then skip directly from the InputStream for the rest.
while (pos < size) {
- int n = (input == null) ? -1 : (int) input.skip(size - pos);
+ final int n = (input == null) ? -1 : (int) input.skip(size - pos);
if (n <= 0) {
throw InvalidProtocolBufferException.truncatedMessage();
}
diff --git a/java/src/main/java/com/google/protobuf/CodedOutputStream.java b/java/src/main/java/com/google/protobuf/CodedOutputStream.java
index 69c22d89..d3907a7c 100644
--- a/java/src/main/java/com/google/protobuf/CodedOutputStream.java
+++ b/java/src/main/java/com/google/protobuf/CodedOutputStream.java
@@ -32,6 +32,7 @@ package com.google.protobuf;
import java.io.OutputStream;
import java.io.IOException;
+import java.io.UnsupportedEncodingException;
/**
* Encodes and writes protocol message fields.
@@ -55,29 +56,30 @@ public final class CodedOutputStream {
private final OutputStream output;
/**
- * The buffer size used in {@link #newInstance(java.io.OutputStream)}.
+ * The buffer size used in {@link #newInstance(OutputStream)}.
*/
public static final int DEFAULT_BUFFER_SIZE = 4096;
- private CodedOutputStream(byte[] buffer, int offset, int length) {
- this.output = null;
+ private CodedOutputStream(final byte[] buffer, final int offset,
+ final int length) {
+ output = null;
this.buffer = buffer;
- this.position = offset;
- this.limit = offset + length;
+ position = offset;
+ limit = offset + length;
}
- private CodedOutputStream(OutputStream output, byte[] buffer) {
+ private CodedOutputStream(final OutputStream output, final byte[] buffer) {
this.output = output;
this.buffer = buffer;
- this.position = 0;
- this.limit = buffer.length;
+ position = 0;
+ limit = buffer.length;
}
/**
* Create a new {@code CodedOutputStream} wrapping the given
* {@code OutputStream}.
*/
- public static CodedOutputStream newInstance(OutputStream output) {
+ public static CodedOutputStream newInstance(final OutputStream output) {
return newInstance(output, DEFAULT_BUFFER_SIZE);
}
@@ -85,8 +87,8 @@ public final class CodedOutputStream {
* Create a new {@code CodedOutputStream} wrapping the given
* {@code OutputStream} with a given buffer size.
*/
- public static CodedOutputStream newInstance(OutputStream output,
- int bufferSize) {
+ public static CodedOutputStream newInstance(final OutputStream output,
+ final int bufferSize) {
return new CodedOutputStream(output, new byte[bufferSize]);
}
@@ -97,7 +99,7 @@ public final class CodedOutputStream {
* array is faster than writing to an {@code OutputStream}. See also
* {@link ByteString#newCodedBuilder}.
*/
- public static CodedOutputStream newInstance(byte[] flatArray) {
+ public static CodedOutputStream newInstance(final byte[] flatArray) {
return newInstance(flatArray, 0, flatArray.length);
}
@@ -108,96 +110,115 @@ public final class CodedOutputStream {
* array is faster than writing to an {@code OutputStream}. See also
* {@link ByteString#newCodedBuilder}.
*/
- public static CodedOutputStream newInstance(byte[] flatArray, int offset,
- int length) {
+ public static CodedOutputStream newInstance(final byte[] flatArray,
+ final int offset,
+ final int length) {
return new CodedOutputStream(flatArray, offset, length);
}
// -----------------------------------------------------------------
/** Write a {@code double} field, including tag, to the stream. */
- public void writeDouble(int fieldNumber, double value) throws IOException {
+ public void writeDouble(final int fieldNumber, final double value)
+ throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
writeDoubleNoTag(value);
}
/** Write a {@code float} field, including tag, to the stream. */
- public void writeFloat(int fieldNumber, float value) throws IOException {
+ public void writeFloat(final int fieldNumber, final float value)
+ throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
writeFloatNoTag(value);
}
/** Write a {@code uint64} field, including tag, to the stream. */
- public void writeUInt64(int fieldNumber, long value) throws IOException {
+ public void writeUInt64(final int fieldNumber, final long value)
+ throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
writeUInt64NoTag(value);
}
/** Write an {@code int64} field, including tag, to the stream. */
- public void writeInt64(int fieldNumber, long value) throws IOException {
+ public void writeInt64(final int fieldNumber, final long value)
+ throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
writeInt64NoTag(value);
}
/** Write an {@code int32} field, including tag, to the stream. */
- public void writeInt32(int fieldNumber, int value) throws IOException {
+ public void writeInt32(final int fieldNumber, final int value)
+ throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
writeInt32NoTag(value);
}
/** Write a {@code fixed64} field, including tag, to the stream. */
- public void writeFixed64(int fieldNumber, long value) throws IOException {
+ public void writeFixed64(final int fieldNumber, final long value)
+ throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
writeFixed64NoTag(value);
}
/** Write a {@code fixed32} field, including tag, to the stream. */
- public void writeFixed32(int fieldNumber, int value) throws IOException {
+ public void writeFixed32(final int fieldNumber, final int value)
+ throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
writeFixed32NoTag(value);
}
/** Write a {@code bool} field, including tag, to the stream. */
- public void writeBool(int fieldNumber, boolean value) throws IOException {
+ public void writeBool(final int fieldNumber, final boolean value)
+ throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
writeBoolNoTag(value);
}
/** Write a {@code string} field, including tag, to the stream. */
- public void writeString(int fieldNumber, String value) throws IOException {
+ public void writeString(final int fieldNumber, final String value)
+ throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeStringNoTag(value);
}
/** Write a {@code group} field, including tag, to the stream. */
- public void writeGroup(int fieldNumber, Message value) throws IOException {
+ public void writeGroup(final int fieldNumber, final MessageLite value)
+ throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
writeGroupNoTag(value);
writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
}
- /** Write a group represented by an {@link UnknownFieldSet}. */
- public void writeUnknownGroup(int fieldNumber, UnknownFieldSet value)
- throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
- writeUnknownGroupNoTag(value);
- writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
+ /**
+ * Write a group represented by an {@link UnknownFieldSet}.
+ *
+ * @deprecated UnknownFieldSet now implements MessageLite, so you can just
+ * call {@link #writeGroup}.
+ */
+ @Deprecated
+ public void writeUnknownGroup(final int fieldNumber,
+ final MessageLite value)
+ throws IOException {
+ writeGroup(fieldNumber, value);
}
/** Write an embedded message field, including tag, to the stream. */
- public void writeMessage(int fieldNumber, Message value) throws IOException {
+ public void writeMessage(final int fieldNumber, final MessageLite value)
+ throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeMessageNoTag(value);
}
/** Write a {@code bytes} field, including tag, to the stream. */
- public void writeBytes(int fieldNumber, ByteString value) throws IOException {
+ public void writeBytes(final int fieldNumber, final ByteString value)
+ throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeBytesNoTag(value);
}
/** Write a {@code uint32} field, including tag, to the stream. */
- public void writeUInt32(int fieldNumber, int value) throws IOException {
+ public void writeUInt32(final int fieldNumber, final int value)
+ throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
writeUInt32NoTag(value);
}
@@ -206,31 +227,36 @@ public final class CodedOutputStream {
* Write an enum field, including tag, to the stream. Caller is responsible
* for converting the enum value to its numeric value.
*/
- public void writeEnum(int fieldNumber, int value) throws IOException {
+ public void writeEnum(final int fieldNumber, final int value)
+ throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
writeEnumNoTag(value);
}
/** Write an {@code sfixed32} field, including tag, to the stream. */
- public void writeSFixed32(int fieldNumber, int value) throws IOException {
+ public void writeSFixed32(final int fieldNumber, final int value)
+ throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
writeSFixed32NoTag(value);
}
/** Write an {@code sfixed64} field, including tag, to the stream. */
- public void writeSFixed64(int fieldNumber, long value) throws IOException {
+ public void writeSFixed64(final int fieldNumber, final long value)
+ throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
writeSFixed64NoTag(value);
}
/** Write an {@code sint32} field, including tag, to the stream. */
- public void writeSInt32(int fieldNumber, int value) throws IOException {
+ public void writeSInt32(final int fieldNumber, final int value)
+ throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
writeSInt32NoTag(value);
}
/** Write an {@code sint64} field, including tag, to the stream. */
- public void writeSInt64(int fieldNumber, long value) throws IOException {
+ public void writeSInt64(final int fieldNumber, final long value)
+ throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
writeSInt64NoTag(value);
}
@@ -239,8 +265,9 @@ public final class CodedOutputStream {
* Write a MessageSet extension field to the stream. For historical reasons,
* the wire format differs from normal fields.
*/
- public void writeMessageSetExtension(int fieldNumber, Message value)
- throws IOException {
+ 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);
@@ -251,7 +278,8 @@ public final class CodedOutputStream {
* Write an unparsed MessageSet extension field to the stream. For
* historical reasons, the wire format differs from normal fields.
*/
- public void writeRawMessageSetExtension(int fieldNumber, ByteString value)
+ 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);
@@ -259,89 +287,30 @@ public final class CodedOutputStream {
writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
}
- /**
- * Write a field of arbitrary type, including tag, to the stream.
- *
- * @param type The field's type.
- * @param number The field's number.
- * @param value Object representing the field's value. Must be of the exact
- * type which would be returned by
- * {@link Message#getField(Descriptors.FieldDescriptor)} for
- * this field.
- */
- public void writeField(Descriptors.FieldDescriptor.Type type,
- int number,
- Object value) throws IOException {
- // Special case for groups, which need a start and end tag; other fields
- // can just use writeTag() and writeFieldNoTag().
- if (type == Descriptors.FieldDescriptor.Type.GROUP) {
- writeGroup(number, (Message) value);
- } else {
- writeTag(number, WireFormat.getWireFormatForFieldType(type));
- writeFieldNoTag(type, value);
- }
- }
-
- /**
- * Write a field of arbitrary type, without its tag, to the stream.
- *
- * @param type The field's type.
- * @param value Object representing the field's value. Must be of the exact
- * type which would be returned by
- * {@link Message#getField(Descriptors.FieldDescriptor)} for
- * this field.
- */
- public void writeFieldNoTag(Descriptors.FieldDescriptor.Type type,
- Object value) throws IOException {
- switch (type) {
- case DOUBLE : writeDoubleNoTag ((Double ) value); break;
- case FLOAT : writeFloatNoTag ((Float ) value); break;
- case INT64 : writeInt64NoTag ((Long ) value); break;
- case UINT64 : writeUInt64NoTag ((Long ) value); break;
- case INT32 : writeInt32NoTag ((Integer ) value); break;
- case FIXED64 : writeFixed64NoTag ((Long ) value); break;
- case FIXED32 : writeFixed32NoTag ((Integer ) value); break;
- case BOOL : writeBoolNoTag ((Boolean ) value); break;
- case STRING : writeStringNoTag ((String ) value); break;
- case GROUP : writeGroupNoTag ((Message ) value); break;
- case MESSAGE : writeMessageNoTag ((Message ) value); break;
- case BYTES : writeBytesNoTag ((ByteString) value); break;
- case UINT32 : writeUInt32NoTag ((Integer ) value); break;
- case SFIXED32: writeSFixed32NoTag((Integer ) value); break;
- case SFIXED64: writeSFixed64NoTag((Long ) value); break;
- case SINT32 : writeSInt32NoTag ((Integer ) value); break;
- case SINT64 : writeSInt64NoTag ((Long ) value); break;
-
- case ENUM:
- writeEnumNoTag(((Descriptors.EnumValueDescriptor) value).getNumber());
- break;
- }
- }
-
// -----------------------------------------------------------------
/** Write a {@code double} field to the stream. */
- public void writeDoubleNoTag(double value) throws IOException {
+ public void writeDoubleNoTag(final double value) throws IOException {
writeRawLittleEndian64(Double.doubleToRawLongBits(value));
}
/** Write a {@code float} field to the stream. */
- public void writeFloatNoTag(float value) throws IOException {
+ public void writeFloatNoTag(final float value) throws IOException {
writeRawLittleEndian32(Float.floatToRawIntBits(value));
}
/** Write a {@code uint64} field to the stream. */
- public void writeUInt64NoTag(long value) throws IOException {
+ public void writeUInt64NoTag(final long value) throws IOException {
writeRawVarint64(value);
}
/** Write an {@code int64} field to the stream. */
- public void writeInt64NoTag(long value) throws IOException {
+ public void writeInt64NoTag(final long value) throws IOException {
writeRawVarint64(value);
}
/** Write an {@code int32} field to the stream. */
- public void writeInt32NoTag(int value) throws IOException {
+ public void writeInt32NoTag(final int value) throws IOException {
if (value >= 0) {
writeRawVarint32(value);
} else {
@@ -351,56 +320,62 @@ public final class CodedOutputStream {
}
/** Write a {@code fixed64} field to the stream. */
- public void writeFixed64NoTag(long value) throws IOException {
+ public void writeFixed64NoTag(final long value) throws IOException {
writeRawLittleEndian64(value);
}
/** Write a {@code fixed32} field to the stream. */
- public void writeFixed32NoTag(int value) throws IOException {
+ public void writeFixed32NoTag(final int value) throws IOException {
writeRawLittleEndian32(value);
}
/** Write a {@code bool} field to the stream. */
- public void writeBoolNoTag(boolean value) throws IOException {
+ public void writeBoolNoTag(final boolean value) throws IOException {
writeRawByte(value ? 1 : 0);
}
/** Write a {@code string} field to the stream. */
- public void writeStringNoTag(String value) throws IOException {
+ public void writeStringNoTag(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.
- byte[] bytes = value.getBytes("UTF-8");
+ final byte[] bytes = value.getBytes("UTF-8");
writeRawVarint32(bytes.length);
writeRawBytes(bytes);
}
/** Write a {@code group} field to the stream. */
- public void writeGroupNoTag(Message value) throws IOException {
+ public void writeGroupNoTag(final MessageLite value) throws IOException {
value.writeTo(this);
}
- /** Write a group represented by an {@link UnknownFieldSet}. */
- public void writeUnknownGroupNoTag(UnknownFieldSet value)
+ /**
+ * Write a group represented by an {@link UnknownFieldSet}.
+ *
+ * @deprecated UnknownFieldSet now implements MessageLite, so you can just
+ * call {@link #writeGroupNoTag}.
+ */
+ @Deprecated
+ public void writeUnknownGroupNoTag(final MessageLite value)
throws IOException {
- value.writeTo(this);
+ writeGroupNoTag(value);
}
/** Write an embedded message field to the stream. */
- public void writeMessageNoTag(Message value) throws IOException {
+ public void writeMessageNoTag(final MessageLite value) throws IOException {
writeRawVarint32(value.getSerializedSize());
value.writeTo(this);
}
/** Write a {@code bytes} field to the stream. */
- public void writeBytesNoTag(ByteString value) throws IOException {
- byte[] bytes = value.toByteArray();
+ public void writeBytesNoTag(final ByteString value) throws IOException {
+ final byte[] bytes = value.toByteArray();
writeRawVarint32(bytes.length);
writeRawBytes(bytes);
}
/** Write a {@code uint32} field to the stream. */
- public void writeUInt32NoTag(int value) throws IOException {
+ public void writeUInt32NoTag(final int value) throws IOException {
writeRawVarint32(value);
}
@@ -408,27 +383,27 @@ public final class CodedOutputStream {
* Write an enum field to the stream. Caller is responsible
* for converting the enum value to its numeric value.
*/
- public void writeEnumNoTag(int value) throws IOException {
+ public void writeEnumNoTag(final int value) throws IOException {
writeRawVarint32(value);
}
/** Write an {@code sfixed32} field to the stream. */
- public void writeSFixed32NoTag(int value) throws IOException {
+ public void writeSFixed32NoTag(final int value) throws IOException {
writeRawLittleEndian32(value);
}
/** Write an {@code sfixed64} field to the stream. */
- public void writeSFixed64NoTag(long value) throws IOException {
+ public void writeSFixed64NoTag(final long value) throws IOException {
writeRawLittleEndian64(value);
}
/** Write an {@code sint32} field to the stream. */
- public void writeSInt32NoTag(int value) throws IOException {
+ public void writeSInt32NoTag(final int value) throws IOException {
writeRawVarint32(encodeZigZag32(value));
}
/** Write an {@code sint64} field to the stream. */
- public void writeSInt64NoTag(long value) throws IOException {
+ public void writeSInt64NoTag(final long value) throws IOException {
writeRawVarint64(encodeZigZag64(value));
}
@@ -438,7 +413,8 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode a
* {@code double} field, including tag.
*/
- public static int computeDoubleSize(int fieldNumber, double value) {
+ public static int computeDoubleSize(final int fieldNumber,
+ final double value) {
return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value);
}
@@ -446,7 +422,7 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode a
* {@code float} field, including tag.
*/
- public static int computeFloatSize(int fieldNumber, float value) {
+ public static int computeFloatSize(final int fieldNumber, final float value) {
return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value);
}
@@ -454,7 +430,7 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode a
* {@code uint64} field, including tag.
*/
- public static int computeUInt64Size(int fieldNumber, long value) {
+ public static int computeUInt64Size(final int fieldNumber, final long value) {
return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value);
}
@@ -462,7 +438,7 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode an
* {@code int64} field, including tag.
*/
- public static int computeInt64Size(int fieldNumber, long value) {
+ public static int computeInt64Size(final int fieldNumber, final long value) {
return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value);
}
@@ -470,7 +446,7 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode an
* {@code int32} field, including tag.
*/
- public static int computeInt32Size(int fieldNumber, int value) {
+ public static int computeInt32Size(final int fieldNumber, final int value) {
return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value);
}
@@ -478,7 +454,8 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode a
* {@code fixed64} field, including tag.
*/
- public static int computeFixed64Size(int fieldNumber, long value) {
+ public static int computeFixed64Size(final int fieldNumber,
+ final long value) {
return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value);
}
@@ -486,7 +463,8 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode a
* {@code fixed32} field, including tag.
*/
- public static int computeFixed32Size(int fieldNumber, int value) {
+ public static int computeFixed32Size(final int fieldNumber,
+ final int value) {
return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value);
}
@@ -494,7 +472,8 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode a
* {@code bool} field, including tag.
*/
- public static int computeBoolSize(int fieldNumber, boolean value) {
+ public static int computeBoolSize(final int fieldNumber,
+ final boolean value) {
return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value);
}
@@ -502,7 +481,8 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode a
* {@code string} field, including tag.
*/
- public static int computeStringSize(int fieldNumber, String value) {
+ public static int computeStringSize(final int fieldNumber,
+ final String value) {
return computeTagSize(fieldNumber) + computeStringSizeNoTag(value);
}
@@ -510,7 +490,8 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode a
* {@code group} field, including tag.
*/
- public static int computeGroupSize(int fieldNumber, Message value) {
+ public static int computeGroupSize(final int fieldNumber,
+ final MessageLite value) {
return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value);
}
@@ -518,18 +499,22 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode a
* {@code group} field represented by an {@code UnknownFieldSet}, including
* tag.
+ *
+ * @deprecated UnknownFieldSet now implements MessageLite, so you can just
+ * call {@link #computeGroupSize}.
*/
- public static int computeUnknownGroupSize(int fieldNumber,
- UnknownFieldSet value) {
- return computeTagSize(fieldNumber) * 2 +
- computeUnknownGroupSizeNoTag(value);
+ @Deprecated
+ public static int computeUnknownGroupSize(final int fieldNumber,
+ final MessageLite value) {
+ return computeGroupSize(fieldNumber, value);
}
/**
* Compute the number of bytes that would be needed to encode an
* embedded message field, including tag.
*/
- public static int computeMessageSize(int fieldNumber, Message value) {
+ public static int computeMessageSize(final int fieldNumber,
+ final MessageLite value) {
return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value);
}
@@ -537,7 +522,8 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode a
* {@code bytes} field, including tag.
*/
- public static int computeBytesSize(int fieldNumber, ByteString value) {
+ public static int computeBytesSize(final int fieldNumber,
+ final ByteString value) {
return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value);
}
@@ -545,7 +531,7 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode a
* {@code uint32} field, including tag.
*/
- public static int computeUInt32Size(int fieldNumber, int value) {
+ public static int computeUInt32Size(final int fieldNumber, final int value) {
return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value);
}
@@ -554,7 +540,7 @@ public final class CodedOutputStream {
* enum field, including tag. Caller is responsible for converting the
* enum value to its numeric value.
*/
- public static int computeEnumSize(int fieldNumber, int value) {
+ public static int computeEnumSize(final int fieldNumber, final int value) {
return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value);
}
@@ -562,7 +548,8 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode an
* {@code sfixed32} field, including tag.
*/
- public static int computeSFixed32Size(int fieldNumber, int value) {
+ public static int computeSFixed32Size(final int fieldNumber,
+ final int value) {
return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value);
}
@@ -570,7 +557,8 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode an
* {@code sfixed64} field, including tag.
*/
- public static int computeSFixed64Size(int fieldNumber, long value) {
+ public static int computeSFixed64Size(final int fieldNumber,
+ final long value) {
return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value);
}
@@ -578,7 +566,7 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode an
* {@code sint32} field, including tag.
*/
- public static int computeSInt32Size(int fieldNumber, int value) {
+ public static int computeSInt32Size(final int fieldNumber, final int value) {
return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value);
}
@@ -586,7 +574,7 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode an
* {@code sint64} field, including tag.
*/
- public static int computeSInt64Size(int fieldNumber, long value) {
+ public static int computeSInt64Size(final int fieldNumber, final long value) {
return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value);
}
@@ -596,7 +584,7 @@ public final class CodedOutputStream {
* the wire format differs from normal fields.
*/
public static int computeMessageSetExtensionSize(
- int fieldNumber, Message value) {
+ final int fieldNumber, final MessageLite value) {
return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2 +
computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber) +
computeMessageSize(WireFormat.MESSAGE_SET_MESSAGE, value);
@@ -608,7 +596,7 @@ public final class CodedOutputStream {
* historical reasons, the wire format differs from normal fields.
*/
public static int computeRawMessageSetExtensionSize(
- int fieldNumber, ByteString value) {
+ final int fieldNumber, final ByteString value) {
return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2 +
computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber) +
computeBytesSize(WireFormat.MESSAGE_SET_MESSAGE, value);
@@ -620,7 +608,7 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode a
* {@code double} field, including tag.
*/
- public static int computeDoubleSizeNoTag(double value) {
+ public static int computeDoubleSizeNoTag(final double value) {
return LITTLE_ENDIAN_64_SIZE;
}
@@ -628,7 +616,7 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode a
* {@code float} field, including tag.
*/
- public static int computeFloatSizeNoTag(float value) {
+ public static int computeFloatSizeNoTag(final float value) {
return LITTLE_ENDIAN_32_SIZE;
}
@@ -636,7 +624,7 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode a
* {@code uint64} field, including tag.
*/
- public static int computeUInt64SizeNoTag(long value) {
+ public static int computeUInt64SizeNoTag(final long value) {
return computeRawVarint64Size(value);
}
@@ -644,7 +632,7 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode an
* {@code int64} field, including tag.
*/
- public static int computeInt64SizeNoTag(long value) {
+ public static int computeInt64SizeNoTag(final long value) {
return computeRawVarint64Size(value);
}
@@ -652,7 +640,7 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode an
* {@code int32} field, including tag.
*/
- public static int computeInt32SizeNoTag(int value) {
+ public static int computeInt32SizeNoTag(final int value) {
if (value >= 0) {
return computeRawVarint32Size(value);
} else {
@@ -665,7 +653,7 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode a
* {@code fixed64} field.
*/
- public static int computeFixed64SizeNoTag(long value) {
+ public static int computeFixed64SizeNoTag(final long value) {
return LITTLE_ENDIAN_64_SIZE;
}
@@ -673,7 +661,7 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode a
* {@code fixed32} field.
*/
- public static int computeFixed32SizeNoTag(int value) {
+ public static int computeFixed32SizeNoTag(final int value) {
return LITTLE_ENDIAN_32_SIZE;
}
@@ -681,7 +669,7 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode a
* {@code bool} field.
*/
- public static int computeBoolSizeNoTag(boolean value) {
+ public static int computeBoolSizeNoTag(final boolean value) {
return 1;
}
@@ -689,12 +677,12 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode a
* {@code string} field.
*/
- public static int computeStringSizeNoTag(String value) {
+ public static int computeStringSizeNoTag(final String value) {
try {
- byte[] bytes = value.getBytes("UTF-8");
+ final byte[] bytes = value.getBytes("UTF-8");
return computeRawVarint32Size(bytes.length) +
bytes.length;
- } catch (java.io.UnsupportedEncodingException e) {
+ } catch (UnsupportedEncodingException e) {
throw new RuntimeException("UTF-8 not supported.", e);
}
}
@@ -703,7 +691,7 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode a
* {@code group} field.
*/
- public static int computeGroupSizeNoTag(Message value) {
+ public static int computeGroupSizeNoTag(final MessageLite value) {
return value.getSerializedSize();
}
@@ -711,17 +699,21 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode a
* {@code group} field represented by an {@code UnknownFieldSet}, including
* tag.
+ *
+ * @deprecated UnknownFieldSet now implements MessageLite, so you can just
+ * call {@link #computeUnknownGroupSizeNoTag}.
*/
- public static int computeUnknownGroupSizeNoTag(UnknownFieldSet value) {
- return value.getSerializedSize();
+ @Deprecated
+ public static int computeUnknownGroupSizeNoTag(final MessageLite value) {
+ return computeGroupSizeNoTag(value);
}
/**
* Compute the number of bytes that would be needed to encode an embedded
* message field.
*/
- public static int computeMessageSizeNoTag(Message value) {
- int size = value.getSerializedSize();
+ public static int computeMessageSizeNoTag(final MessageLite value) {
+ final int size = value.getSerializedSize();
return computeRawVarint32Size(size) + size;
}
@@ -729,7 +721,7 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode a
* {@code bytes} field.
*/
- public static int computeBytesSizeNoTag(ByteString value) {
+ public static int computeBytesSizeNoTag(final ByteString value) {
return computeRawVarint32Size(value.size()) +
value.size();
}
@@ -738,15 +730,15 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode a
* {@code uint32} field.
*/
- public static int computeUInt32SizeNoTag(int value) {
+ public static int computeUInt32SizeNoTag(final int value) {
return computeRawVarint32Size(value);
}
/**
- * Compute the number of bytes that would be needed to encode an enum field.
+ * Compute the number of bytes that would be needed to encode an enum field.
* Caller is responsible for converting the enum value to its numeric value.
*/
- public static int computeEnumSizeNoTag(int value) {
+ public static int computeEnumSizeNoTag(final int value) {
return computeRawVarint32Size(value);
}
@@ -754,7 +746,7 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode an
* {@code sfixed32} field.
*/
- public static int computeSFixed32SizeNoTag(int value) {
+ public static int computeSFixed32SizeNoTag(final int value) {
return LITTLE_ENDIAN_32_SIZE;
}
@@ -762,7 +754,7 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode an
* {@code sfixed64} field.
*/
- public static int computeSFixed64SizeNoTag(long value) {
+ public static int computeSFixed64SizeNoTag(final long value) {
return LITTLE_ENDIAN_64_SIZE;
}
@@ -770,7 +762,7 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode an
* {@code sint32} field.
*/
- public static int computeSInt32SizeNoTag(int value) {
+ public static int computeSInt32SizeNoTag(final int value) {
return computeRawVarint32Size(encodeZigZag32(value));
}
@@ -778,71 +770,10 @@ public final class CodedOutputStream {
* Compute the number of bytes that would be needed to encode an
* {@code sint64} field.
*/
- public static int computeSInt64SizeNoTag(long value) {
+ public static int computeSInt64SizeNoTag(final long value) {
return computeRawVarint64Size(encodeZigZag64(value));
}
- /**
- * Compute the number of bytes that would be needed to encode a
- * field of arbitrary type, including tag, to the stream.
- *
- * @param type The field's type.
- * @param number The field's number.
- * @param value Object representing the field's value. Must be of the exact
- * type which would be returned by
- * {@link Message#getField(Descriptors.FieldDescriptor)} for
- * this field.
- */
- public static int computeFieldSize(
- Descriptors.FieldDescriptor.Type type,
- int number, Object value) {
- int tagSize = computeTagSize(number);
- if (type == Descriptors.FieldDescriptor.Type.GROUP) {
- tagSize *= 2;
- }
- return tagSize + computeFieldSizeNoTag(type, value);
- }
-
- /**
- * Compute the number of bytes that would be needed to encode a
- * field of arbitrary type, excluding tag, to the stream.
- *
- * @param type The field's type.
- * @param value Object representing the field's value. Must be of the exact
- * type which would be returned by
- * {@link Message#getField(Descriptors.FieldDescriptor)} for
- * this field.
- */
- public static int computeFieldSizeNoTag(
- Descriptors.FieldDescriptor.Type type, Object value) {
- switch (type) {
- case DOUBLE : return computeDoubleSizeNoTag ((Double )value);
- case FLOAT : return computeFloatSizeNoTag ((Float )value);
- case INT64 : return computeInt64SizeNoTag ((Long )value);
- case UINT64 : return computeUInt64SizeNoTag ((Long )value);
- case INT32 : return computeInt32SizeNoTag ((Integer )value);
- case FIXED64 : return computeFixed64SizeNoTag ((Long )value);
- case FIXED32 : return computeFixed32SizeNoTag ((Integer )value);
- case BOOL : return computeBoolSizeNoTag ((Boolean )value);
- case STRING : return computeStringSizeNoTag ((String )value);
- case GROUP : return computeGroupSizeNoTag ((Message )value);
- case MESSAGE : return computeMessageSizeNoTag ((Message )value);
- case BYTES : return computeBytesSizeNoTag ((ByteString)value);
- case UINT32 : return computeUInt32SizeNoTag ((Integer )value);
- case SFIXED32: return computeSFixed32SizeNoTag((Integer )value);
- case SFIXED64: return computeSFixed64SizeNoTag((Long )value);
- case SINT32 : return computeSInt32SizeNoTag ((Integer )value);
- case SINT64 : return computeSInt64SizeNoTag ((Long )value);
-
- case ENUM:
- return computeEnumSizeNoTag(
- ((Descriptors.EnumValueDescriptor)value).getNumber());
- }
-
- throw new RuntimeException(
- "There is no way to get here, but the compiler thinks otherwise.");
- }
-
// =================================================================
/**
@@ -905,6 +836,8 @@ public final class CodedOutputStream {
* this exception will be thrown.
*/
public static class OutOfSpaceException extends IOException {
+ private static final long serialVersionUID = -6947486886997889499L;
+
OutOfSpaceException() {
super("CodedOutputStream was writing to a flat byte array and ran " +
"out of space.");
@@ -912,7 +845,7 @@ public final class CodedOutputStream {
}
/** Write a single byte. */
- public void writeRawByte(byte value) throws IOException {
+ public void writeRawByte(final byte value) throws IOException {
if (position == limit) {
refreshBuffer();
}
@@ -921,17 +854,17 @@ public final class CodedOutputStream {
}
/** Write a single byte, represented by an integer value. */
- public void writeRawByte(int value) throws IOException {
+ public void writeRawByte(final int value) throws IOException {
writeRawByte((byte) value);
}
/** Write an array of bytes. */
- public void writeRawBytes(byte[] value) throws IOException {
+ public void writeRawBytes(final byte[] value) throws IOException {
writeRawBytes(value, 0, value.length);
}
/** Write part of an array of bytes. */
- public void writeRawBytes(byte[] value, int offset, int length)
+ public void writeRawBytes(final byte[] value, int offset, int length)
throws IOException {
if (limit - position >= length) {
// We have room in the current buffer.
@@ -940,7 +873,7 @@ public final class CodedOutputStream {
} else {
// Write extends past current buffer. Fill the rest of this buffer and
// flush.
- int bytesWritten = limit - position;
+ final int bytesWritten = limit - position;
System.arraycopy(value, offset, buffer, position, bytesWritten);
offset += bytesWritten;
length -= bytesWritten;
@@ -962,12 +895,13 @@ public final class CodedOutputStream {
}
/** Encode and write a tag. */
- public void writeTag(int fieldNumber, int wireType) throws IOException {
+ public void writeTag(final int fieldNumber, final int wireType)
+ throws IOException {
writeRawVarint32(WireFormat.makeTag(fieldNumber, wireType));
}
/** Compute the number of bytes that would be needed to encode a tag. */
- public static int computeTagSize(int fieldNumber) {
+ public static int computeTagSize(final int fieldNumber) {
return computeRawVarint32Size(WireFormat.makeTag(fieldNumber, 0));
}
@@ -992,7 +926,7 @@ public final class CodedOutputStream {
* {@code value} is treated as unsigned, so it won't be sign-extended if
* negative.
*/
- public static int computeRawVarint32Size(int value) {
+ public static int computeRawVarint32Size(final int value) {
if ((value & (0xffffffff << 7)) == 0) return 1;
if ((value & (0xffffffff << 14)) == 0) return 2;
if ((value & (0xffffffff << 21)) == 0) return 3;
@@ -1014,7 +948,7 @@ public final class CodedOutputStream {
}
/** Compute the number of bytes that would be needed to encode a varint. */
- public static int computeRawVarint64Size(long value) {
+ public static int computeRawVarint64Size(final long value) {
if ((value & (0xffffffffffffffffL << 7)) == 0) return 1;
if ((value & (0xffffffffffffffffL << 14)) == 0) return 2;
if ((value & (0xffffffffffffffffL << 21)) == 0) return 3;
@@ -1028,7 +962,7 @@ public final class CodedOutputStream {
}
/** Write a little-endian 32-bit integer. */
- public void writeRawLittleEndian32(int value) throws IOException {
+ public void writeRawLittleEndian32(final int value) throws IOException {
writeRawByte((value ) & 0xFF);
writeRawByte((value >> 8) & 0xFF);
writeRawByte((value >> 16) & 0xFF);
@@ -1038,7 +972,7 @@ public final class CodedOutputStream {
public static final int LITTLE_ENDIAN_32_SIZE = 4;
/** Write a little-endian 64-bit integer. */
- public void writeRawLittleEndian64(long value) throws IOException {
+ public void writeRawLittleEndian64(final long value) throws IOException {
writeRawByte((int)(value ) & 0xFF);
writeRawByte((int)(value >> 8) & 0xFF);
writeRawByte((int)(value >> 16) & 0xFF);
@@ -1061,7 +995,7 @@ public final class CodedOutputStream {
* @return An unsigned 32-bit integer, stored in a signed int because
* Java has no explicit unsigned support.
*/
- public static int encodeZigZag32(int n) {
+ public static int encodeZigZag32(final int n) {
// Note: the right-shift must be arithmetic
return (n << 1) ^ (n >> 31);
}
@@ -1076,7 +1010,7 @@ public final class CodedOutputStream {
* @return An unsigned 64-bit integer, stored in a signed int because
* Java has no explicit unsigned support.
*/
- public static long encodeZigZag64(long n) {
+ public static long encodeZigZag64(final long n) {
// Note: the right-shift must be arithmetic
return (n << 1) ^ (n >> 63);
}
diff --git a/java/src/main/java/com/google/protobuf/Descriptors.java b/java/src/main/java/com/google/protobuf/Descriptors.java
index 24499efb..0d5e47d1 100644
--- a/java/src/main/java/com/google/protobuf/Descriptors.java
+++ b/java/src/main/java/com/google/protobuf/Descriptors.java
@@ -37,11 +37,12 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.io.UnsupportedEncodingException;
/**
* Contains a collection of classes which describe protocol message types.
*
- * Every message type has a {@link Descriptors.Descriptor}, which lists all
+ * Every message type has a {@link Descriptor}, which lists all
* its fields and other information about a type. You can get a message
* type's descriptor by calling {@code MessageType.getDescriptor()}, or
* (given a message object of the type) {@code message.getDescriptorForType()}.
@@ -106,11 +107,13 @@ public final class Descriptors {
public Descriptor findMessageTypeByName(String name) {
// Don't allow looking up nested types. This will make optimization
// easier later.
- if (name.indexOf('.') != -1) return null;
+ if (name.indexOf('.') != -1) {
+ return null;
+ }
if (getPackage().length() > 0) {
- name = getPackage() + "." + name;
+ name = getPackage() + '.' + name;
}
- GenericDescriptor result = pool.findSymbol(name);
+ final GenericDescriptor result = pool.findSymbol(name);
if (result != null && result instanceof Descriptor &&
result.getFile() == this) {
return (Descriptor)result;
@@ -128,11 +131,13 @@ public final class Descriptors {
public EnumDescriptor findEnumTypeByName(String name) {
// Don't allow looking up nested types. This will make optimization
// easier later.
- if (name.indexOf('.') != -1) return null;
+ if (name.indexOf('.') != -1) {
+ return null;
+ }
if (getPackage().length() > 0) {
- name = getPackage() + "." + name;
+ name = getPackage() + '.' + name;
}
- GenericDescriptor result = pool.findSymbol(name);
+ final GenericDescriptor result = pool.findSymbol(name);
if (result != null && result instanceof EnumDescriptor &&
result.getFile() == this) {
return (EnumDescriptor)result;
@@ -150,11 +155,13 @@ public final class Descriptors {
public ServiceDescriptor findServiceByName(String name) {
// Don't allow looking up nested types. This will make optimization
// easier later.
- if (name.indexOf('.') != -1) return null;
+ if (name.indexOf('.') != -1) {
+ return null;
+ }
if (getPackage().length() > 0) {
- name = getPackage() + "." + name;
+ name = getPackage() + '.' + name;
}
- GenericDescriptor result = pool.findSymbol(name);
+ final GenericDescriptor result = pool.findSymbol(name);
if (result != null && result instanceof ServiceDescriptor &&
result.getFile() == this) {
return (ServiceDescriptor)result;
@@ -171,11 +178,13 @@ public final class Descriptors {
* @return The extension's descriptor, or {@code null} if not found.
*/
public FieldDescriptor findExtensionByName(String name) {
- if (name.indexOf('.') != -1) return null;
+ if (name.indexOf('.') != -1) {
+ return null;
+ }
if (getPackage().length() > 0) {
- name = getPackage() + "." + name;
+ name = getPackage() + '.' + name;
}
- GenericDescriptor result = pool.findSymbol(name);
+ final GenericDescriptor result = pool.findSymbol(name);
if (result != null && result instanceof FieldDescriptor &&
result.getFile() == this) {
return (FieldDescriptor)result;
@@ -196,8 +205,8 @@ public final class Descriptors {
* because a field has an undefined type or because two messages
* were defined with the same name.
*/
- public static FileDescriptor buildFrom(FileDescriptorProto proto,
- FileDescriptor[] dependencies)
+ public static FileDescriptor buildFrom(final FileDescriptorProto proto,
+ final FileDescriptor[] dependencies)
throws DescriptorValidationException {
// Building decsriptors involves two steps: translating and linking.
// In the translation step (implemented by FileDescriptor's
@@ -208,8 +217,9 @@ public final class Descriptors {
// FieldDescriptor for an embedded message contains a pointer directly
// to the Descriptor for that message's type. We also detect undefined
// types in the linking step.
- DescriptorPool pool = new DescriptorPool(dependencies);
- FileDescriptor result = new FileDescriptor(proto, dependencies, pool);
+ final DescriptorPool pool = new DescriptorPool(dependencies);
+ final FileDescriptor result =
+ new FileDescriptor(proto, dependencies, pool);
if (dependencies.length != proto.getDependencyCount()) {
throw new DescriptorValidationException(result,
@@ -234,8 +244,8 @@ public final class Descriptors {
* encoded in protocol buffer wire format.
*/
public static void internalBuildGeneratedFileFrom(
- String descriptorData, FileDescriptor[] dependencies,
- InternalDescriptorAssigner descriptorAssigner) {
+ final String descriptorData, final FileDescriptor[] dependencies,
+ final InternalDescriptorAssigner descriptorAssigner) {
// Hack: We can't embed a raw byte array inside generated Java code
// (at least, not efficiently), but we can embed Strings. So, the
// protocol compiler embeds the FileDescriptorProto as a giant
@@ -245,10 +255,10 @@ public final class Descriptors {
// serialized form. So, if we convert it to bytes in ISO-8859-1, we
// should get the original bytes that we want.
- byte[] descriptorBytes;
+ final byte[] descriptorBytes;
try {
descriptorBytes = descriptorData.getBytes("ISO-8859-1");
- } catch (java.io.UnsupportedEncodingException e) {
+ } catch (UnsupportedEncodingException e) {
throw new RuntimeException(
"Standard encoding ISO-8859-1 not supported by JVM.", e);
}
@@ -261,7 +271,7 @@ public final class Descriptors {
"Failed to parse protocol buffer descriptor for generated code.", e);
}
- FileDescriptor result;
+ final FileDescriptor result;
try {
result = buildFrom(proto, dependencies);
} catch (DescriptorValidationException e) {
@@ -269,7 +279,8 @@ public final class Descriptors {
"Invalid embedded descriptor for \"" + proto.getName() + "\".", e);
}
- ExtensionRegistry registry = descriptorAssigner.assignDescriptors(result);
+ final ExtensionRegistry registry =
+ descriptorAssigner.assignDescriptors(result);
if (registry != null) {
// We must re-parse the proto using the registry.
@@ -297,7 +308,7 @@ public final class Descriptors {
* descriptor.proto. The callback may also return null to indicate that
* no extensions are used in the decsriptor.
*/
- public static interface InternalDescriptorAssigner {
+ public interface InternalDescriptorAssigner {
ExtensionRegistry assignDescriptors(FileDescriptor root);
}
@@ -309,9 +320,9 @@ public final class Descriptors {
private final FileDescriptor[] dependencies;
private final DescriptorPool pool;
- private FileDescriptor(FileDescriptorProto proto,
- FileDescriptor[] dependencies,
- DescriptorPool pool)
+ private FileDescriptor(final FileDescriptorProto proto,
+ final FileDescriptor[] dependencies,
+ final DescriptorPool pool)
throws DescriptorValidationException {
this.pool = pool;
this.proto = proto;
@@ -344,16 +355,16 @@ public final class Descriptors {
/** Look up and cross-link all field types, etc. */
private void crossLink() throws DescriptorValidationException {
- for (int i = 0; i < messageTypes.length; i++) {
- messageTypes[i].crossLink();
+ for (final Descriptor messageType : messageTypes) {
+ messageType.crossLink();
}
- for (int i = 0; i < services.length; i++) {
- services[i].crossLink();
+ for (final ServiceDescriptor service : services) {
+ service.crossLink();
}
- for (int i = 0; i < extensions.length; i++) {
- extensions[i].crossLink();
+ for (final FieldDescriptor extension : extensions) {
+ extension.crossLink();
}
}
@@ -367,7 +378,7 @@ public final class Descriptors {
* protos. So, we have to parse the descriptor protos a second time after
* constructing the descriptors.
*/
- private void setProto(FileDescriptorProto proto) {
+ private void setProto(final FileDescriptorProto proto) {
this.proto = proto;
for (int i = 0; i < messageTypes.length; i++) {
@@ -456,8 +467,9 @@ public final class Descriptors {
}
/** Determines if the given field number is an extension. */
- public boolean isExtensionNumber(int number) {
- for (DescriptorProto.ExtensionRange range : proto.getExtensionRangeList()) {
+ public boolean isExtensionNumber(final int number) {
+ for (final DescriptorProto.ExtensionRange range :
+ proto.getExtensionRangeList()) {
if (range.getStart() <= number && number < range.getEnd()) {
return true;
}
@@ -470,8 +482,9 @@ public final class Descriptors {
* @param name The unqualified name of the field (e.g. "foo").
* @return The field's descriptor, or {@code null} if not found.
*/
- public FieldDescriptor findFieldByName(String name) {
- GenericDescriptor result = file.pool.findSymbol(fullName + "." + name);
+ public FieldDescriptor findFieldByName(final String name) {
+ final GenericDescriptor result =
+ file.pool.findSymbol(fullName + '.' + name);
if (result != null && result instanceof FieldDescriptor) {
return (FieldDescriptor)result;
} else {
@@ -484,7 +497,7 @@ public final class Descriptors {
* @param number The field number within this message type.
* @return The field's descriptor, or {@code null} if not found.
*/
- public FieldDescriptor findFieldByNumber(int number) {
+ public FieldDescriptor findFieldByNumber(final int number) {
return file.pool.fieldsByNumber.get(
new DescriptorPool.DescriptorIntPair(this, number));
}
@@ -494,8 +507,9 @@ public final class Descriptors {
* @param name The unqualified name of the nested type (e.g. "Foo").
* @return The types's descriptor, or {@code null} if not found.
*/
- public Descriptor findNestedTypeByName(String name) {
- GenericDescriptor result = file.pool.findSymbol(fullName + "." + name);
+ public Descriptor findNestedTypeByName(final String name) {
+ final GenericDescriptor result =
+ file.pool.findSymbol(fullName + '.' + name);
if (result != null && result instanceof Descriptor) {
return (Descriptor)result;
} else {
@@ -508,8 +522,9 @@ public final class Descriptors {
* @param name The unqualified name of the nested type (e.g. "Foo").
* @return The types's descriptor, or {@code null} if not found.
*/
- public EnumDescriptor findEnumTypeByName(String name) {
- GenericDescriptor result = file.pool.findSymbol(fullName + "." + name);
+ public EnumDescriptor findEnumTypeByName(final String name) {
+ final GenericDescriptor result =
+ file.pool.findSymbol(fullName + '.' + name);
if (result != null && result instanceof EnumDescriptor) {
return (EnumDescriptor)result;
} else {
@@ -527,38 +542,38 @@ public final class Descriptors {
private final FieldDescriptor[] fields;
private final FieldDescriptor[] extensions;
- private Descriptor(DescriptorProto proto,
- FileDescriptor file,
- Descriptor parent,
- int index)
+ private Descriptor(final DescriptorProto proto,
+ final FileDescriptor file,
+ final Descriptor parent,
+ final int index)
throws DescriptorValidationException {
this.index = index;
this.proto = proto;
- this.fullName = computeFullName(file, parent, proto.getName());
+ fullName = computeFullName(file, parent, proto.getName());
this.file = file;
- this.containingType = parent;
+ containingType = parent;
- this.nestedTypes = new Descriptor[proto.getNestedTypeCount()];
+ nestedTypes = new Descriptor[proto.getNestedTypeCount()];
for (int i = 0; i < proto.getNestedTypeCount(); i++) {
- this.nestedTypes[i] = new Descriptor(
+ nestedTypes[i] = new Descriptor(
proto.getNestedType(i), file, this, i);
}
- this.enumTypes = new EnumDescriptor[proto.getEnumTypeCount()];
+ enumTypes = new EnumDescriptor[proto.getEnumTypeCount()];
for (int i = 0; i < proto.getEnumTypeCount(); i++) {
- this.enumTypes[i] = new EnumDescriptor(
+ enumTypes[i] = new EnumDescriptor(
proto.getEnumType(i), file, this, i);
}
- this.fields = new FieldDescriptor[proto.getFieldCount()];
+ fields = new FieldDescriptor[proto.getFieldCount()];
for (int i = 0; i < proto.getFieldCount(); i++) {
- this.fields[i] = new FieldDescriptor(
+ fields[i] = new FieldDescriptor(
proto.getField(i), file, this, i, false);
}
- this.extensions = new FieldDescriptor[proto.getExtensionCount()];
+ extensions = new FieldDescriptor[proto.getExtensionCount()];
for (int i = 0; i < proto.getExtensionCount(); i++) {
- this.extensions[i] = new FieldDescriptor(
+ extensions[i] = new FieldDescriptor(
proto.getExtension(i), file, this, i, true);
}
@@ -567,21 +582,21 @@ public final class Descriptors {
/** Look up and cross-link all field types, etc. */
private void crossLink() throws DescriptorValidationException {
- for (int i = 0; i < nestedTypes.length; i++) {
- nestedTypes[i].crossLink();
+ for (final Descriptor nestedType : nestedTypes) {
+ nestedType.crossLink();
}
- for (int i = 0; i < fields.length; i++) {
- fields[i].crossLink();
+ for (final FieldDescriptor field : fields) {
+ field.crossLink();
}
- for (int i = 0; i < extensions.length; i++) {
- extensions[i].crossLink();
+ for (final FieldDescriptor extension : extensions) {
+ extension.crossLink();
}
}
- /** See {@link FileDescriptor.setProto}. */
- private void setProto(DescriptorProto proto) {
+ /** See {@link FileDescriptor#setProto}. */
+ private void setProto(final DescriptorProto proto) {
this.proto = proto;
for (int i = 0; i < nestedTypes.length; i++) {
@@ -606,10 +621,11 @@ public final class Descriptors {
/** Describes a field of a message type. */
public static final class FieldDescriptor
- implements GenericDescriptor, Comparable<FieldDescriptor> {
+ implements GenericDescriptor, Comparable<FieldDescriptor>,
+ FieldSet.FieldDescriptorLite<FieldDescriptor> {
/**
* Get the index of this descriptor within its parent.
- * @see Descriptors.Descriptor#getIndex()
+ * @see Descriptor#getIndex()
*/
public int getIndex() { return index; }
@@ -624,7 +640,7 @@ public final class Descriptors {
/**
* Get the field's fully-qualified name.
- * @see Descriptors.Descriptor#getFullName()
+ * @see Descriptor#getFullName()
*/
public String getFullName() { return fullName; }
@@ -634,12 +650,27 @@ public final class Descriptors {
*/
public JavaType getJavaType() { return type.getJavaType(); }
+ /** For internal use only. */
+ public WireFormat.JavaType getLiteJavaType() {
+ return getLiteType().getJavaType();
+ }
+
/** Get the {@code FileDescriptor} containing this descriptor. */
public FileDescriptor getFile() { return file; }
/** Get the field's declared type. */
public Type getType() { return type; }
+ /** For internal use only. */
+ public WireFormat.FieldType getLiteType() {
+ return table[type.ordinal()];
+ }
+ // I'm pretty sure values() constructs a new array every time, since there
+ // is nothing stopping the caller from mutating the array. Therefore we
+ // make a static copy here.
+ private static final WireFormat.FieldType[] table =
+ WireFormat.FieldType.values();
+
/** Is this field declared required? */
public boolean isRequired() {
return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REQUIRED;
@@ -655,6 +686,11 @@ public final class Descriptors {
return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REPEATED;
}
+ /** Does this field have the {@code [packed = true]} option? */
+ public boolean isPacked() {
+ return getOptions().getPacked();
+ }
+
/** Returns true if the field had an explicitly-defined default value. */
public boolean hasDefaultValue() { return proto.hasDefaultValue(); }
@@ -742,7 +778,7 @@ public final class Descriptors {
* @return negative, zero, or positive if {@code this} is less than,
* equal to, or greater than {@code other}, respectively.
*/
- public int compareTo(FieldDescriptor other) {
+ public int compareTo(final FieldDescriptor other) {
if (other.containingType != containingType) {
throw new IllegalArgumentException(
"FieldDescriptors can only be compared to other FieldDescriptors " +
@@ -765,7 +801,7 @@ public final class Descriptors {
private EnumDescriptor enumType;
private Object defaultValue;
- public static enum Type {
+ public enum Type {
DOUBLE (FieldDescriptorProto.Type.TYPE_DOUBLE , JavaType.DOUBLE ),
FLOAT (FieldDescriptorProto.Type.TYPE_FLOAT , JavaType.FLOAT ),
INT64 (FieldDescriptorProto.Type.TYPE_INT64 , JavaType.LONG ),
@@ -785,11 +821,11 @@ public final class Descriptors {
SINT32 (FieldDescriptorProto.Type.TYPE_SINT32 , JavaType.INT ),
SINT64 (FieldDescriptorProto.Type.TYPE_SINT64 , JavaType.LONG );
- private Type(FieldDescriptorProto.Type proto, JavaType javaType) {
+ Type(final FieldDescriptorProto.Type proto, final JavaType javaType) {
this.proto = proto;
this.javaType = javaType;
- if (this.ordinal() != proto.getNumber() - 1) {
+ if (ordinal() != proto.getNumber() - 1) {
throw new RuntimeException(
"descriptor.proto changed but Desrciptors.java wasn't updated.");
}
@@ -801,7 +837,7 @@ public final class Descriptors {
public FieldDescriptorProto.Type toProto() { return proto; }
public JavaType getJavaType() { return javaType; }
- public static Type valueOf(FieldDescriptorProto.Type type) {
+ public static Type valueOf(final FieldDescriptorProto.Type type) {
return values()[type.getNumber() - 1];
}
}
@@ -815,7 +851,7 @@ public final class Descriptors {
}
}
- public static enum JavaType {
+ public enum JavaType {
INT(0),
LONG(0L),
FLOAT(0F),
@@ -826,7 +862,7 @@ public final class Descriptors {
ENUM(null),
MESSAGE(null);
- private JavaType(Object defaultDefault) {
+ JavaType(final Object defaultDefault) {
this.defaultDefault = defaultDefault;
}
@@ -834,22 +870,22 @@ public final class Descriptors {
* The default default value for fields of this type, if it's a primitive
* type. This is meant for use inside this file only, hence is private.
*/
- private Object defaultDefault;
+ private final Object defaultDefault;
}
- private FieldDescriptor(FieldDescriptorProto proto,
- FileDescriptor file,
- Descriptor parent,
- int index,
- boolean isExtension)
+ private FieldDescriptor(final FieldDescriptorProto proto,
+ final FileDescriptor file,
+ final Descriptor parent,
+ final int index,
+ final boolean isExtension)
throws DescriptorValidationException {
this.index = index;
this.proto = proto;
- this.fullName = computeFullName(file, parent, proto.getName());
+ fullName = computeFullName(file, parent, proto.getName());
this.file = file;
if (proto.hasType()) {
- this.type = Type.valueOf(proto.getType());
+ type = Type.valueOf(proto.getType());
}
if (getNumber() <= 0) {
@@ -875,19 +911,19 @@ public final class Descriptors {
throw new DescriptorValidationException(this,
"FieldDescriptorProto.extendee not set for extension field.");
}
- this.containingType = null; // Will be filled in when cross-linking
+ containingType = null; // Will be filled in when cross-linking
if (parent != null) {
- this.extensionScope = parent;
+ extensionScope = parent;
} else {
- this.extensionScope = null;
+ extensionScope = null;
}
} else {
if (proto.hasExtendee()) {
throw new DescriptorValidationException(this,
"FieldDescriptorProto.extendee set for non-extension field.");
}
- this.containingType = parent;
- this.extensionScope = null;
+ containingType = parent;
+ extensionScope = null;
}
file.pool.addSymbol(this);
@@ -896,43 +932,44 @@ public final class Descriptors {
/** Look up and cross-link all field types, etc. */
private void crossLink() throws DescriptorValidationException {
if (proto.hasExtendee()) {
- GenericDescriptor extendee =
+ final GenericDescriptor extendee =
file.pool.lookupSymbol(proto.getExtendee(), this);
if (!(extendee instanceof Descriptor)) {
throw new DescriptorValidationException(this,
- "\"" + proto.getExtendee() + "\" is not a message type.");
+ '\"' + proto.getExtendee() + "\" is not a message type.");
}
- this.containingType = (Descriptor)extendee;
+ containingType = (Descriptor)extendee;
if (!getContainingType().isExtensionNumber(getNumber())) {
throw new DescriptorValidationException(this,
- "\"" + getContainingType().getFullName() + "\" does not declare " +
- getNumber() + " as an extension number.");
+ '\"' + getContainingType().getFullName() +
+ "\" does not declare " + getNumber() +
+ " as an extension number.");
}
}
if (proto.hasTypeName()) {
- GenericDescriptor typeDescriptor =
+ final GenericDescriptor typeDescriptor =
file.pool.lookupSymbol(proto.getTypeName(), this);
if (!proto.hasType()) {
// Choose field type based on symbol.
if (typeDescriptor instanceof Descriptor) {
- this.type = Type.MESSAGE;
+ type = Type.MESSAGE;
} else if (typeDescriptor instanceof EnumDescriptor) {
- this.type = Type.ENUM;
+ type = Type.ENUM;
} else {
throw new DescriptorValidationException(this,
- "\"" + proto.getTypeName() + "\" is not a type.");
+ '\"' + proto.getTypeName() + "\" is not a type.");
}
}
if (getJavaType() == JavaType.MESSAGE) {
if (!(typeDescriptor instanceof Descriptor)) {
throw new DescriptorValidationException(this,
- "\"" + proto.getTypeName() + "\" is not a message type.");
+ '\"' + proto.getTypeName() + "\" is not a message type.");
}
- this.messageType = (Descriptor)typeDescriptor;
+ messageType = (Descriptor)typeDescriptor;
if (proto.hasDefaultValue()) {
throw new DescriptorValidationException(this,
@@ -941,9 +978,9 @@ public final class Descriptors {
} else if (getJavaType() == JavaType.ENUM) {
if (!(typeDescriptor instanceof EnumDescriptor)) {
throw new DescriptorValidationException(this,
- "\"" + proto.getTypeName() + "\" is not an enum type.");
+ '\"' + proto.getTypeName() + "\" is not an enum type.");
}
- this.enumType = (EnumDescriptor)typeDescriptor;
+ enumType = (EnumDescriptor)typeDescriptor;
} else {
throw new DescriptorValidationException(this,
"Field with primitive type has type_name.");
@@ -972,20 +1009,18 @@ public final class Descriptors {
defaultValue = TextFormat.parseInt32(proto.getDefaultValue());
break;
case UINT32:
- case FIXED32: {
+ case FIXED32:
defaultValue = TextFormat.parseUInt32(proto.getDefaultValue());
break;
- }
case INT64:
case SINT64:
case SFIXED64:
defaultValue = TextFormat.parseInt64(proto.getDefaultValue());
break;
case UINT64:
- case FIXED64: {
+ case FIXED64:
defaultValue = TextFormat.parseUInt64(proto.getDefaultValue());
break;
- }
case FLOAT:
defaultValue = Float.valueOf(proto.getDefaultValue());
break;
@@ -1002,9 +1037,9 @@ public final class Descriptors {
try {
defaultValue =
TextFormat.unescapeBytes(proto.getDefaultValue());
- } catch (TextFormat.InvalidEscapeSequence e) {
+ } catch (TextFormat.InvalidEscapeSequenceException e) {
throw new DescriptorValidationException(this,
- "Couldn't parse default value: " + e.getMessage());
+ "Couldn't parse default value: " + e.getMessage(), e);
}
break;
case ENUM:
@@ -1012,7 +1047,7 @@ public final class Descriptors {
if (defaultValue == null) {
throw new DescriptorValidationException(this,
"Unknown enum default value: \"" +
- proto.getDefaultValue() + "\"");
+ proto.getDefaultValue() + '\"');
}
break;
case MESSAGE:
@@ -1021,17 +1056,17 @@ public final class Descriptors {
"Message type had default value.");
}
} catch (NumberFormatException e) {
- DescriptorValidationException validationException =
+ final DescriptorValidationException validationException =
new DescriptorValidationException(this,
"Could not parse default value: \"" +
- proto.getDefaultValue() + "\"");
+ proto.getDefaultValue() + '\"');
validationException.initCause(e);
throw validationException;
}
} else {
// Determine the default default for this field.
if (isRepeated()) {
- defaultValue = Collections.EMPTY_LIST;
+ defaultValue = Collections.emptyList();
} else {
switch (getJavaType()) {
case ENUM:
@@ -1067,19 +1102,32 @@ public final class Descriptors {
}
}
- /** See {@link FileDescriptor.setProto}. */
- private void setProto(FieldDescriptorProto proto) {
+ /** See {@link FileDescriptor#setProto}. */
+ private void setProto(final FieldDescriptorProto proto) {
this.proto = proto;
}
+
+ /**
+ * For internal use only. This is to satisfy the FieldDescriptorLite
+ * interface.
+ */
+ @Override
+ public MessageLite.Builder internalMergeFrom(
+ MessageLite.Builder to, MessageLite from) {
+ // FieldDescriptors are only used with non-lite messages so we can just
+ // down-cast and call mergeFrom directly.
+ return ((Message.Builder) to).mergeFrom((Message) from);
+ }
}
// =================================================================
/** Describes an enum type. */
- public static final class EnumDescriptor implements GenericDescriptor {
+ public static final class EnumDescriptor
+ implements GenericDescriptor, Internal.EnumLiteMap<EnumValueDescriptor> {
/**
* Get the index of this descriptor within its parent.
- * @see Descriptors.Descriptor#getIndex()
+ * @see Descriptor#getIndex()
*/
public int getIndex() { return index; }
@@ -1091,7 +1139,7 @@ public final class Descriptors {
/**
* Get the type's fully-qualified name.
- * @see Descriptors.Descriptor#getFullName()
+ * @see Descriptor#getFullName()
*/
public String getFullName() { return fullName; }
@@ -1114,8 +1162,9 @@ public final class Descriptors {
* @param name The unqualified name of the value (e.g. "FOO").
* @return the value's decsriptor, or {@code null} if not found.
*/
- public EnumValueDescriptor findValueByName(String name) {
- GenericDescriptor result = file.pool.findSymbol(fullName + "." + name);
+ public EnumValueDescriptor findValueByName(final String name) {
+ final GenericDescriptor result =
+ file.pool.findSymbol(fullName + '.' + name);
if (result != null && result instanceof EnumValueDescriptor) {
return (EnumValueDescriptor)result;
} else {
@@ -1129,7 +1178,7 @@ public final class Descriptors {
* @param number The value's number.
* @return the value's decsriptor, or {@code null} if not found.
*/
- public EnumValueDescriptor findValueByNumber(int number) {
+ public EnumValueDescriptor findValueByNumber(final int number) {
return file.pool.enumValuesByNumber.get(
new DescriptorPool.DescriptorIntPair(this, number));
}
@@ -1141,16 +1190,16 @@ public final class Descriptors {
private final Descriptor containingType;
private EnumValueDescriptor[] values;
- private EnumDescriptor(EnumDescriptorProto proto,
- FileDescriptor file,
- Descriptor parent,
- int index)
+ private EnumDescriptor(final EnumDescriptorProto proto,
+ final FileDescriptor file,
+ final Descriptor parent,
+ final int index)
throws DescriptorValidationException {
this.index = index;
this.proto = proto;
- this.fullName = computeFullName(file, parent, proto.getName());
+ fullName = computeFullName(file, parent, proto.getName());
this.file = file;
- this.containingType = parent;
+ containingType = parent;
if (proto.getValueCount() == 0) {
// We cannot allow enums with no values because this would mean there
@@ -1161,15 +1210,15 @@ public final class Descriptors {
values = new EnumValueDescriptor[proto.getValueCount()];
for (int i = 0; i < proto.getValueCount(); i++) {
- this.values[i] = new EnumValueDescriptor(
+ values[i] = new EnumValueDescriptor(
proto.getValue(i), file, this, i);
}
file.pool.addSymbol(this);
}
- /** See {@link FileDescriptor.setProto}. */
- private void setProto(EnumDescriptorProto proto) {
+ /** See {@link FileDescriptor#setProto}. */
+ private void setProto(final EnumDescriptorProto proto) {
this.proto = proto;
for (int i = 0; i < values.length; i++) {
@@ -1186,10 +1235,11 @@ public final class Descriptors {
* with the same number after the first become aliases of the first.
* However, they still have independent EnumValueDescriptors.
*/
- public static final class EnumValueDescriptor implements GenericDescriptor {
+ public static final class EnumValueDescriptor
+ implements GenericDescriptor, Internal.EnumLite {
/**
* Get the index of this descriptor within its parent.
- * @see Descriptors.Descriptor#getIndex()
+ * @see Descriptor#getIndex()
*/
public int getIndex() { return index; }
@@ -1204,7 +1254,7 @@ public final class Descriptors {
/**
* Get the value's fully-qualified name.
- * @see Descriptors.Descriptor#getFullName()
+ * @see Descriptor#getFullName()
*/
public String getFullName() { return fullName; }
@@ -1225,24 +1275,24 @@ public final class Descriptors {
private final FileDescriptor file;
private final EnumDescriptor type;
- private EnumValueDescriptor(EnumValueDescriptorProto proto,
- FileDescriptor file,
- EnumDescriptor parent,
- int index)
+ private EnumValueDescriptor(final EnumValueDescriptorProto proto,
+ final FileDescriptor file,
+ final EnumDescriptor parent,
+ final int index)
throws DescriptorValidationException {
this.index = index;
this.proto = proto;
this.file = file;
- this.type = parent;
+ type = parent;
- this.fullName = parent.getFullName() + "." + proto.getName();
+ fullName = parent.getFullName() + '.' + proto.getName();
file.pool.addSymbol(this);
file.pool.addEnumValueByNumber(this);
}
- /** See {@link FileDescriptor.setProto}. */
- private void setProto(EnumValueDescriptorProto proto) {
+ /** See {@link FileDescriptor#setProto}. */
+ private void setProto(final EnumValueDescriptorProto proto) {
this.proto = proto;
}
}
@@ -1265,7 +1315,7 @@ public final class Descriptors {
/**
* Get the type's fully-qualified name.
- * @see Descriptors.Descriptor#getFullName()
+ * @see Descriptor#getFullName()
*/
public String getFullName() { return fullName; }
@@ -1285,8 +1335,9 @@ public final class Descriptors {
* @param name The unqualified name of the method (e.g. "Foo").
* @return the method's decsriptor, or {@code null} if not found.
*/
- public MethodDescriptor findMethodByName(String name) {
- GenericDescriptor result = file.pool.findSymbol(fullName + "." + name);
+ public MethodDescriptor findMethodByName(final String name) {
+ final GenericDescriptor result =
+ file.pool.findSymbol(fullName + '.' + name);
if (result != null && result instanceof MethodDescriptor) {
return (MethodDescriptor)result;
} else {
@@ -1300,18 +1351,18 @@ public final class Descriptors {
private final FileDescriptor file;
private MethodDescriptor[] methods;
- private ServiceDescriptor(ServiceDescriptorProto proto,
- FileDescriptor file,
- int index)
+ private ServiceDescriptor(final ServiceDescriptorProto proto,
+ final FileDescriptor file,
+ final int index)
throws DescriptorValidationException {
this.index = index;
this.proto = proto;
- this.fullName = computeFullName(file, null, proto.getName());
+ fullName = computeFullName(file, null, proto.getName());
this.file = file;
- this.methods = new MethodDescriptor[proto.getMethodCount()];
+ methods = new MethodDescriptor[proto.getMethodCount()];
for (int i = 0; i < proto.getMethodCount(); i++) {
- this.methods[i] = new MethodDescriptor(
+ methods[i] = new MethodDescriptor(
proto.getMethod(i), file, this, i);
}
@@ -1319,13 +1370,13 @@ public final class Descriptors {
}
private void crossLink() throws DescriptorValidationException {
- for (int i = 0; i < methods.length; i++) {
- methods[i].crossLink();
+ for (final MethodDescriptor method : methods) {
+ method.crossLink();
}
}
- /** See {@link FileDescriptor.setProto}. */
- private void setProto(ServiceDescriptorProto proto) {
+ /** See {@link FileDescriptor#setProto}. */
+ private void setProto(final ServiceDescriptorProto proto) {
this.proto = proto;
for (int i = 0; i < methods.length; i++) {
@@ -1354,7 +1405,7 @@ public final class Descriptors {
/**
* Get the method's fully-qualified name.
- * @see Descriptors.Descriptor#getFullName()
+ * @see Descriptor#getFullName()
*/
public String getFullName() { return fullName; }
@@ -1385,54 +1436,54 @@ public final class Descriptors {
private Descriptor inputType;
private Descriptor outputType;
- private MethodDescriptor(MethodDescriptorProto proto,
- FileDescriptor file,
- ServiceDescriptor parent,
- int index)
+ private MethodDescriptor(final MethodDescriptorProto proto,
+ final FileDescriptor file,
+ final ServiceDescriptor parent,
+ final int index)
throws DescriptorValidationException {
this.index = index;
this.proto = proto;
this.file = file;
- this.service = parent;
+ service = parent;
- this.fullName = parent.getFullName() + "." + proto.getName();
+ fullName = parent.getFullName() + '.' + proto.getName();
file.pool.addSymbol(this);
}
private void crossLink() throws DescriptorValidationException {
- GenericDescriptor inputType =
+ final GenericDescriptor input =
file.pool.lookupSymbol(proto.getInputType(), this);
- if (!(inputType instanceof Descriptor)) {
+ if (!(input instanceof Descriptor)) {
throw new DescriptorValidationException(this,
- "\"" + proto.getInputType() + "\" is not a message type.");
+ '\"' + proto.getInputType() + "\" is not a message type.");
}
- this.inputType = (Descriptor)inputType;
+ inputType = (Descriptor)input;
- GenericDescriptor outputType =
+ final GenericDescriptor output =
file.pool.lookupSymbol(proto.getOutputType(), this);
- if (!(outputType instanceof Descriptor)) {
+ if (!(output instanceof Descriptor)) {
throw new DescriptorValidationException(this,
- "\"" + proto.getOutputType() + "\" is not a message type.");
+ '\"' + proto.getOutputType() + "\" is not a message type.");
}
- this.outputType = (Descriptor)outputType;
+ outputType = (Descriptor)output;
}
- /** See {@link FileDescriptor.setProto}. */
- private void setProto(MethodDescriptorProto proto) {
+ /** See {@link FileDescriptor#setProto}. */
+ private void setProto(final MethodDescriptorProto proto) {
this.proto = proto;
}
}
// =================================================================
- private static String computeFullName(FileDescriptor file,
- Descriptor parent,
- String name) {
+ private static String computeFullName(final FileDescriptor file,
+ final Descriptor parent,
+ final String name) {
if (parent != null) {
- return parent.getFullName() + "." + name;
+ return parent.getFullName() + '.' + name;
} else if (file.getPackage().length() > 0) {
- return file.getPackage() + "." + name;
+ return file.getPackage() + '.' + name;
} else {
return name;
}
@@ -1444,7 +1495,7 @@ public final class Descriptors {
* All descriptors except {@code FileDescriptor} implement this to make
* {@code DescriptorPool}'s life easier.
*/
- private static interface GenericDescriptor {
+ private interface GenericDescriptor {
Message toProto();
String getName();
String getFullName();
@@ -1456,6 +1507,8 @@ public final class Descriptors {
* are not valid.
*/
public static class DescriptorValidationException extends Exception {
+ private static final long serialVersionUID = 5750205775490483148L;
+
/** Gets the full name of the descriptor where the error occurred. */
public String getProblemSymbolName() { return name; }
@@ -1473,27 +1526,36 @@ public final class Descriptors {
private final Message proto;
private final String description;
- private DescriptorValidationException(GenericDescriptor problemDescriptor,
- String description) {
- super(problemDescriptor.getFullName() + ": " + description);
+ private DescriptorValidationException(
+ final GenericDescriptor problemDescriptor,
+ final String description) {
+ this(problemDescriptor, description, null);
+ }
+
+ private DescriptorValidationException(
+ final GenericDescriptor problemDescriptor,
+ final String description,
+ final Throwable cause) {
+ super(problemDescriptor.getFullName() + ": " + description, cause);
// Note that problemDescriptor may be partially uninitialized, so we
// don't want to expose it directly to the user. So, we only provide
// the name and the original proto.
- this.name = problemDescriptor.getFullName();
- this.proto = problemDescriptor.toProto();
+ name = problemDescriptor.getFullName();
+ proto = problemDescriptor.toProto();
this.description = description;
}
- private DescriptorValidationException(FileDescriptor problemDescriptor,
- String description) {
+ private DescriptorValidationException(
+ final FileDescriptor problemDescriptor,
+ final String description) {
super(problemDescriptor.getName() + ": " + description);
// Note that problemDescriptor may be partially uninitialized, so we
// don't want to expose it directly to the user. So, we only provide
// the name and the original proto.
- this.name = problemDescriptor.getName();
- this.proto = problemDescriptor.toProto();
+ name = problemDescriptor.getName();
+ proto = problemDescriptor.toProto();
this.description = description;
}
}
@@ -1505,16 +1567,16 @@ public final class Descriptors {
* descriptors defined in a particular file.
*/
private static final class DescriptorPool {
- DescriptorPool(FileDescriptor[] dependencies) {
+ DescriptorPool(final FileDescriptor[] dependencies) {
this.dependencies = new DescriptorPool[dependencies.length];
for (int i = 0; i < dependencies.length; i++) {
this.dependencies[i] = dependencies[i].pool;
}
- for (int i = 0; i < dependencies.length; i++) {
+ for (final FileDescriptor dependency : dependencies) {
try {
- addPackage(dependencies[i].getPackage(), dependencies[i]);
+ addPackage(dependency.getPackage(), dependency);
} catch (DescriptorValidationException e) {
// Can't happen, because addPackage() only fails when the name
// conflicts with a non-package, but we have not yet added any
@@ -1524,23 +1586,27 @@ public final class Descriptors {
}
}
- final DescriptorPool[] dependencies;
+ private final DescriptorPool[] dependencies;
- final Map<String, GenericDescriptor> descriptorsByName =
+ private final Map<String, GenericDescriptor> descriptorsByName =
new HashMap<String, GenericDescriptor>();
- final Map<DescriptorIntPair, FieldDescriptor> fieldsByNumber =
+ private final Map<DescriptorIntPair, FieldDescriptor> fieldsByNumber =
new HashMap<DescriptorIntPair, FieldDescriptor>();
- final Map<DescriptorIntPair, EnumValueDescriptor> enumValuesByNumber =
- new HashMap<DescriptorIntPair, EnumValueDescriptor>();
+ private final Map<DescriptorIntPair, EnumValueDescriptor> enumValuesByNumber
+ = new HashMap<DescriptorIntPair, EnumValueDescriptor>();
/** Find a generic descriptor by fully-qualified name. */
- GenericDescriptor findSymbol(String fullName) {
+ GenericDescriptor findSymbol(final String fullName) {
GenericDescriptor result = descriptorsByName.get(fullName);
- if (result != null) return result;
+ if (result != null) {
+ return result;
+ }
- for (int i = 0; i < dependencies.length; i++) {
- result = dependencies[i].descriptorsByName.get(fullName);
- if (result != null) return result;
+ for (final DescriptorPool dependency : dependencies) {
+ result = dependency.descriptorsByName.get(fullName);
+ if (result != null) {
+ return result;
+ }
}
return null;
@@ -1552,8 +1618,8 @@ public final class Descriptors {
* partially-qualified, or unqualified. C++-like name lookup semantics
* are used to search for the matching descriptor.
*/
- GenericDescriptor lookupSymbol(String name,
- GenericDescriptor relativeTo)
+ GenericDescriptor lookupSymbol(final String name,
+ final GenericDescriptor relativeTo)
throws DescriptorValidationException {
// TODO(kenton): This could be optimized in a number of ways.
@@ -1564,8 +1630,8 @@ public final class Descriptors {
} else {
// If "name" is a compound identifier, we want to search for the
// first component of it, then search within it for the rest.
- int firstPartLength = name.indexOf('.');
- String firstPart;
+ final int firstPartLength = name.indexOf('.');
+ final String firstPart;
if (firstPartLength == -1) {
firstPart = name;
} else {
@@ -1574,11 +1640,12 @@ public final class Descriptors {
// We will search each parent scope of "relativeTo" looking for the
// symbol.
- StringBuilder scopeToTry = new StringBuilder(relativeTo.getFullName());
+ final StringBuilder scopeToTry =
+ new StringBuilder(relativeTo.getFullName());
while (true) {
// Chop off the last component of the scope.
- int dotpos = scopeToTry.lastIndexOf(".");
+ final int dotpos = scopeToTry.lastIndexOf(".");
if (dotpos == -1) {
result = findSymbol(name);
break;
@@ -1609,7 +1676,7 @@ public final class Descriptors {
if (result == null) {
throw new DescriptorValidationException(relativeTo,
- "\"" + name + "\" is not defined.");
+ '\"' + name + "\" is not defined.");
} else {
return result;
}
@@ -1619,30 +1686,30 @@ public final class Descriptors {
* Adds a symbol to the symbol table. If a symbol with the same name
* already exists, throws an error.
*/
- void addSymbol(GenericDescriptor descriptor)
+ void addSymbol(final GenericDescriptor descriptor)
throws DescriptorValidationException {
validateSymbolName(descriptor);
- String fullName = descriptor.getFullName();
- int dotpos = fullName.lastIndexOf('.');
+ final String fullName = descriptor.getFullName();
+ final int dotpos = fullName.lastIndexOf('.');
- GenericDescriptor old = descriptorsByName.put(fullName, descriptor);
+ final GenericDescriptor old = descriptorsByName.put(fullName, descriptor);
if (old != null) {
descriptorsByName.put(fullName, old);
if (descriptor.getFile() == old.getFile()) {
if (dotpos == -1) {
throw new DescriptorValidationException(descriptor,
- "\"" + fullName + "\" is already defined.");
+ '\"' + fullName + "\" is already defined.");
} else {
throw new DescriptorValidationException(descriptor,
- "\"" + fullName.substring(dotpos + 1) +
+ '\"' + fullName.substring(dotpos + 1) +
"\" is already defined in \"" +
fullName.substring(0, dotpos) + "\".");
}
} else {
throw new DescriptorValidationException(descriptor,
- "\"" + fullName + "\" is already defined in file \"" +
+ '\"' + fullName + "\" is already defined in file \"" +
old.getFile().getName() + "\".");
}
}
@@ -1653,21 +1720,22 @@ public final class Descriptors {
* just as placeholders so that someone cannot define, say, a message type
* that has the same name as an existing package.
*/
- static final class PackageDescriptor implements GenericDescriptor {
+ private static final class PackageDescriptor implements GenericDescriptor {
public Message toProto() { return file.toProto(); }
public String getName() { return name; }
public String getFullName() { return fullName; }
public FileDescriptor getFile() { return file; }
- PackageDescriptor(String name, String fullName, FileDescriptor file) {
+ PackageDescriptor(final String name, final String fullName,
+ final FileDescriptor file) {
this.file = file;
this.fullName = fullName;
this.name = name;
}
- String name;
- String fullName;
- FileDescriptor file;
+ private final String name;
+ private final String fullName;
+ private final FileDescriptor file;
}
/**
@@ -1676,46 +1744,50 @@ public final class Descriptors {
* under the same name, an exception is thrown. If the package has
* multiple components, this also adds the parent package(s).
*/
- void addPackage(String fullName, FileDescriptor file)
+ void addPackage(final String fullName, final FileDescriptor file)
throws DescriptorValidationException {
- int dotpos = fullName.lastIndexOf('.');
- String name;
- if (dotpos != -1) {
+ final int dotpos = fullName.lastIndexOf('.');
+ final String name;
+ if (dotpos == -1) {
+ name = fullName;
+ } else {
addPackage(fullName.substring(0, dotpos), file);
name = fullName.substring(dotpos + 1);
- } else {
- name = fullName;
}
- GenericDescriptor old =
+ final GenericDescriptor old =
descriptorsByName.put(fullName,
new PackageDescriptor(name, fullName, file));
if (old != null) {
descriptorsByName.put(fullName, old);
if (!(old instanceof PackageDescriptor)) {
throw new DescriptorValidationException(file,
- "\"" + name + "\" is already defined (as something other than a " +
- "package) in file \"" + old.getFile().getName() + "\".");
+ '\"' + name + "\" is already defined (as something other than a "
+ + "package) in file \"" + old.getFile().getName() + "\".");
}
}
}
/** A (GenericDescriptor, int) pair, used as a map key. */
- static final class DescriptorIntPair {
- final GenericDescriptor descriptor;
- final int number;
+ private static final class DescriptorIntPair {
+ private final GenericDescriptor descriptor;
+ private final int number;
- DescriptorIntPair(GenericDescriptor descriptor, int number) {
+ DescriptorIntPair(final GenericDescriptor descriptor, final int number) {
this.descriptor = descriptor;
this.number = number;
}
+ @Override
public int hashCode() {
return descriptor.hashCode() * ((1 << 16) - 1) + number;
}
- public boolean equals(Object obj) {
- if (!(obj instanceof DescriptorIntPair)) return false;
- DescriptorIntPair other = (DescriptorIntPair)obj;
+ @Override
+ public boolean equals(final Object obj) {
+ if (!(obj instanceof DescriptorIntPair)) {
+ return false;
+ }
+ final DescriptorIntPair other = (DescriptorIntPair)obj;
return descriptor == other.descriptor && number == other.number;
}
}
@@ -1724,11 +1796,11 @@ public final class Descriptors {
* Adds a field to the fieldsByNumber table. Throws an exception if a
* field with hte same containing type and number already exists.
*/
- void addFieldByNumber(FieldDescriptor field)
+ void addFieldByNumber(final FieldDescriptor field)
throws DescriptorValidationException {
- DescriptorIntPair key =
+ final DescriptorIntPair key =
new DescriptorIntPair(field.getContainingType(), field.getNumber());
- FieldDescriptor old = fieldsByNumber.put(key, field);
+ final FieldDescriptor old = fieldsByNumber.put(key, field);
if (old != null) {
fieldsByNumber.put(key, old);
throw new DescriptorValidationException(field,
@@ -1744,10 +1816,10 @@ public final class Descriptors {
* with the same type and number already exists, does nothing. (This is
* allowed; the first value define with the number takes precedence.)
*/
- void addEnumValueByNumber(EnumValueDescriptor value) {
- DescriptorIntPair key =
+ void addEnumValueByNumber(final EnumValueDescriptor value) {
+ final DescriptorIntPair key =
new DescriptorIntPair(value.getType(), value.getNumber());
- EnumValueDescriptor old = enumValuesByNumber.put(key, value);
+ final EnumValueDescriptor old = enumValuesByNumber.put(key, value);
if (old != null) {
enumValuesByNumber.put(key, old);
// Not an error: Multiple enum values may have the same number, but
@@ -1759,15 +1831,15 @@ public final class Descriptors {
* Verifies that the descriptor's name is valid (i.e. it contains only
* letters, digits, and underscores, and does not start with a digit).
*/
- void validateSymbolName(GenericDescriptor descriptor)
- throws DescriptorValidationException {
- String name = descriptor.getName();
+ static void validateSymbolName(final GenericDescriptor descriptor)
+ throws DescriptorValidationException {
+ final String name = descriptor.getName();
if (name.length() == 0) {
throw new DescriptorValidationException(descriptor, "Missing name.");
} else {
boolean valid = true;
for (int i = 0; i < name.length(); i++) {
- char c = name.charAt(i);
+ final char c = name.charAt(i);
// Non-ASCII characters are not valid in protobuf identifiers, even
// if they are letters or digits.
if (c >= 128) {
@@ -1784,7 +1856,7 @@ public final class Descriptors {
}
if (!valid) {
throw new DescriptorValidationException(descriptor,
- "\"" + name + "\" is not a valid identifier.");
+ '\"' + name + "\" is not a valid identifier.");
}
}
}
diff --git a/java/src/main/java/com/google/protobuf/DynamicMessage.java b/java/src/main/java/com/google/protobuf/DynamicMessage.java
index 59fb7b02..c106b662 100644
--- a/java/src/main/java/com/google/protobuf/DynamicMessage.java
+++ b/java/src/main/java/com/google/protobuf/DynamicMessage.java
@@ -45,14 +45,14 @@ import java.util.Map;
*/
public final class DynamicMessage extends AbstractMessage {
private final Descriptor type;
- private final FieldSet fields;
+ private final FieldSet<FieldDescriptor> fields;
private final UnknownFieldSet unknownFields;
private int memoizedSize = -1;
/**
* Construct a {@code DynamicMessage} using the given {@code FieldSet}.
*/
- private DynamicMessage(Descriptor type, FieldSet fields,
+ private DynamicMessage(Descriptor type, FieldSet<FieldDescriptor> fields,
UnknownFieldSet unknownFields) {
this.type = type;
this.fields = fields;
@@ -64,7 +64,7 @@ public final class DynamicMessage extends AbstractMessage {
* given type.
*/
public static DynamicMessage getDefaultInstance(Descriptor type) {
- return new DynamicMessage(type, FieldSet.emptySet(),
+ return new DynamicMessage(type, FieldSet.<FieldDescriptor>emptySet(),
UnknownFieldSet.getDefaultInstance());
}
@@ -160,7 +160,11 @@ public final class DynamicMessage extends AbstractMessage {
verifyContainingType(field);
Object result = fields.getField(field);
if (result == null) {
- result = getDefaultInstance(field.getMessageType());
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ result = getDefaultInstance(field.getMessageType());
+ } else {
+ result = field.getDefaultValue();
+ }
}
return result;
}
@@ -179,15 +183,31 @@ public final class DynamicMessage extends AbstractMessage {
return unknownFields;
}
+ private static boolean isInitialized(Descriptor type,
+ FieldSet<FieldDescriptor> fields) {
+ // Check that all required fields are present.
+ for (final FieldDescriptor field : type.getFields()) {
+ if (field.isRequired()) {
+ if (!fields.hasField(field)) {
+ return false;
+ }
+ }
+ }
+
+ // Check that embedded messages are initialized.
+ return fields.isInitialized();
+ }
+
public boolean isInitialized() {
- return fields.isInitialized(type);
+ return isInitialized(type, fields);
}
public void writeTo(CodedOutputStream output) throws IOException {
- fields.writeTo(output);
if (type.getOptions().getMessageSetWireFormat()) {
+ fields.writeMessageSetTo(output);
unknownFields.writeAsMessageSetTo(output);
} else {
+ fields.writeTo(output);
unknownFields.writeTo(output);
}
}
@@ -196,10 +216,11 @@ public final class DynamicMessage extends AbstractMessage {
int size = memoizedSize;
if (size != -1) return size;
- size = fields.getSerializedSize();
if (type.getOptions().getMessageSetWireFormat()) {
+ size = fields.getMessageSetSerializedSize();
size += unknownFields.getSerializedSizeAsMessageSet();
} else {
+ size = fields.getSerializedSize();
size += unknownFields.getSerializedSize();
}
@@ -230,7 +251,7 @@ public final class DynamicMessage extends AbstractMessage {
*/
public static final class Builder extends AbstractMessage.Builder<Builder> {
private final Descriptor type;
- private FieldSet fields;
+ private FieldSet<FieldDescriptor> fields;
private UnknownFieldSet unknownFields;
/** Construct a {@code Builder} for the given type. */
@@ -244,25 +265,33 @@ public final class DynamicMessage extends AbstractMessage {
// Implementation of Message.Builder interface.
public Builder clear() {
+ if (fields == null) {
+ throw new IllegalStateException("Cannot call clear() after build().");
+ }
fields.clear();
return this;
}
public Builder mergeFrom(Message other) {
- if (other.getDescriptorForType() != type) {
- throw new IllegalArgumentException(
- "mergeFrom(Message) can only merge messages of the same type.");
+ if (other instanceof DynamicMessage) {
+ // This should be somewhat faster than calling super.mergeFrom().
+ DynamicMessage otherDynamicMessage = (DynamicMessage) other;
+ if (otherDynamicMessage.type != type) {
+ throw new IllegalArgumentException(
+ "mergeFrom(Message) can only merge messages of the same type.");
+ }
+ fields.mergeFrom(otherDynamicMessage.fields);
+ mergeUnknownFields(otherDynamicMessage.unknownFields);
+ return this;
+ } else {
+ return super.mergeFrom(other);
}
-
- fields.mergeFrom(other);
- mergeUnknownFields(other.getUnknownFields());
- return this;
}
public DynamicMessage build() {
// If fields == null, we'll throw an appropriate exception later.
if (fields != null && !isInitialized()) {
- throw new UninitializedMessageException(
+ throw newUninitializedMessageException(
new DynamicMessage(type, fields, unknownFields));
}
return buildPartial();
@@ -275,7 +304,7 @@ public final class DynamicMessage extends AbstractMessage {
*/
private DynamicMessage buildParsed() throws InvalidProtocolBufferException {
if (!isInitialized()) {
- throw new UninitializedMessageException(
+ throw newUninitializedMessageException(
new DynamicMessage(type, fields, unknownFields))
.asInvalidProtocolBufferException();
}
@@ -302,17 +331,7 @@ public final class DynamicMessage extends AbstractMessage {
}
public boolean isInitialized() {
- return fields.isInitialized(type);
- }
-
- public Builder mergeFrom(CodedInputStream input,
- ExtensionRegistry extensionRegistry)
- throws IOException {
- UnknownFieldSet.Builder unknownFieldsBuilder =
- UnknownFieldSet.newBuilder(unknownFields);
- fields.mergeFrom(input, unknownFieldsBuilder, extensionRegistry, this);
- unknownFields = unknownFieldsBuilder.build();
- return this;
+ return DynamicMessage.isInitialized(type, fields);
}
public Descriptor getDescriptorForType() {
@@ -347,7 +366,11 @@ public final class DynamicMessage extends AbstractMessage {
verifyContainingType(field);
Object result = fields.getField(field);
if (result == null) {
- result = getDefaultInstance(field.getMessageType());
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ result = getDefaultInstance(field.getMessageType());
+ } else {
+ result = field.getDefaultValue();
+ }
}
return result;
}
diff --git a/java/src/main/java/com/google/protobuf/ExtensionRegistry.java b/java/src/main/java/com/google/protobuf/ExtensionRegistry.java
index 45396f6f..87bbd6eb 100644
--- a/java/src/main/java/com/google/protobuf/ExtensionRegistry.java
+++ b/java/src/main/java/com/google/protobuf/ExtensionRegistry.java
@@ -84,18 +84,16 @@ import java.util.Map;
* would be slow. Second, corrupt data would not be detected until first
* access, at which point it would be much harder to deal with it. Third, it
* could violate the expectation that message objects are immutable, since the
- * type provided could be any arbitrary message class. An unpriviledged user
+ * type provided could be any arbitrary message class. An unprivileged user
* could take advantage of this to inject a mutable object into a message
- * belonging to priviledged code and create mischief.
+ * belonging to privileged code and create mischief.
*
* @author kenton@google.com Kenton Varda
*/
-public final class ExtensionRegistry {
+public final class ExtensionRegistry extends ExtensionRegistryLite {
/** Construct a new, empty instance. */
public static ExtensionRegistry newInstance() {
- return new ExtensionRegistry(
- new HashMap<String, ExtensionInfo>(),
- new HashMap<DescriptorIntPair, ExtensionInfo>());
+ return new ExtensionRegistry();
}
/** Get the unmodifiable singleton empty instance. */
@@ -104,10 +102,9 @@ public final class ExtensionRegistry {
}
/** Returns an unmodifiable view of the registry. */
+ @Override
public ExtensionRegistry getUnmodifiable() {
- return new ExtensionRegistry(
- Collections.unmodifiableMap(extensionsByName),
- Collections.unmodifiableMap(extensionsByNumber));
+ return new ExtensionRegistry(this);
}
/** A (Descriptor, Message) pair, returned by lookup methods. */
@@ -121,11 +118,12 @@ public final class ExtensionRegistry {
*/
public final Message defaultInstance;
- private ExtensionInfo(FieldDescriptor descriptor) {
+ private ExtensionInfo(final FieldDescriptor descriptor) {
this.descriptor = descriptor;
- this.defaultInstance = null;
+ defaultInstance = null;
}
- private ExtensionInfo(FieldDescriptor descriptor, Message defaultInstance) {
+ private ExtensionInfo(final FieldDescriptor descriptor,
+ final Message defaultInstance) {
this.descriptor = descriptor;
this.defaultInstance = defaultInstance;
}
@@ -139,7 +137,7 @@ public final class ExtensionRegistry {
* @return Information about the extension if found, or {@code null}
* otherwise.
*/
- public ExtensionInfo findExtensionByName(String fullName) {
+ public ExtensionInfo findExtensionByName(final String fullName) {
return extensionsByName.get(fullName);
}
@@ -149,14 +147,14 @@ public final class ExtensionRegistry {
* @return Information about the extension if found, or {@code null}
* otherwise.
*/
- public ExtensionInfo findExtensionByNumber(Descriptor containingType,
- int fieldNumber) {
+ public ExtensionInfo findExtensionByNumber(final Descriptor containingType,
+ final int fieldNumber) {
return extensionsByNumber.get(
new DescriptorIntPair(containingType, fieldNumber));
}
/** Add an extension from a generated file to the registry. */
- public void add(GeneratedMessage.GeneratedExtension<?, ?> extension) {
+ public void add(final GeneratedMessage.GeneratedExtension<?, ?> extension) {
if (extension.getDescriptor().getJavaType() ==
FieldDescriptor.JavaType.MESSAGE) {
add(new ExtensionInfo(extension.getDescriptor(),
@@ -167,7 +165,7 @@ public final class ExtensionRegistry {
}
/** Add a non-message-type extension to the registry by descriptor. */
- public void add(FieldDescriptor type) {
+ public void add(final FieldDescriptor type) {
if (type.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
throw new IllegalArgumentException(
"ExtensionRegistry.add() must be provided a default instance when " +
@@ -177,7 +175,7 @@ public final class ExtensionRegistry {
}
/** Add a message-type extension to the registry by descriptor. */
- public void add(FieldDescriptor type, Message defaultInstance) {
+ public void add(final FieldDescriptor type, final Message defaultInstance) {
if (type.getJavaType() != FieldDescriptor.JavaType.MESSAGE) {
throw new IllegalArgumentException(
"ExtensionRegistry.add() provided a default instance for a " +
@@ -189,22 +187,30 @@ public final class ExtensionRegistry {
// =================================================================
// Private stuff.
- private ExtensionRegistry(
- Map<String, ExtensionInfo> extensionsByName,
- Map<DescriptorIntPair, ExtensionInfo> extensionsByNumber) {
- this.extensionsByName = extensionsByName;
- this.extensionsByNumber = extensionsByNumber;
+ private ExtensionRegistry() {
+ this.extensionsByName = new HashMap<String, ExtensionInfo>();
+ this.extensionsByNumber = new HashMap<DescriptorIntPair, ExtensionInfo>();
+ }
+
+ private ExtensionRegistry(ExtensionRegistry other) {
+ super(other);
+ this.extensionsByName = Collections.unmodifiableMap(other.extensionsByName);
+ this.extensionsByNumber =
+ Collections.unmodifiableMap(other.extensionsByNumber);
}
private final Map<String, ExtensionInfo> extensionsByName;
private final Map<DescriptorIntPair, ExtensionInfo> extensionsByNumber;
- private static final ExtensionRegistry EMPTY =
- new ExtensionRegistry(
- Collections.<String, ExtensionInfo>emptyMap(),
- Collections.<DescriptorIntPair, ExtensionInfo>emptyMap());
+ private ExtensionRegistry(boolean empty) {
+ super(ExtensionRegistryLite.getEmptyRegistry());
+ this.extensionsByName = Collections.<String, ExtensionInfo>emptyMap();
+ this.extensionsByNumber =
+ Collections.<DescriptorIntPair, ExtensionInfo>emptyMap();
+ }
+ private static final ExtensionRegistry EMPTY = new ExtensionRegistry(true);
- private void add(ExtensionInfo extension) {
+ private void add(final ExtensionInfo extension) {
if (!extension.descriptor.isExtension()) {
throw new IllegalArgumentException(
"ExtensionRegistry.add() was given a FieldDescriptor for a regular " +
@@ -217,7 +223,7 @@ public final class ExtensionRegistry {
extension.descriptor.getNumber()),
extension);
- FieldDescriptor field = extension.descriptor;
+ final FieldDescriptor field = extension.descriptor;
if (field.getContainingType().getOptions().getMessageSetWireFormat() &&
field.getType() == FieldDescriptor.Type.MESSAGE &&
field.isOptional() &&
@@ -231,20 +237,24 @@ public final class ExtensionRegistry {
/** A (GenericDescriptor, int) pair, used as a map key. */
private static final class DescriptorIntPair {
- final Descriptor descriptor;
- final int number;
+ private final Descriptor descriptor;
+ private final int number;
- DescriptorIntPair(Descriptor descriptor, int number) {
+ DescriptorIntPair(final Descriptor descriptor, final int number) {
this.descriptor = descriptor;
this.number = number;
}
+ @Override
public int hashCode() {
return descriptor.hashCode() * ((1 << 16) - 1) + number;
}
- public boolean equals(Object obj) {
- if (!(obj instanceof DescriptorIntPair)) return false;
- DescriptorIntPair other = (DescriptorIntPair)obj;
+ @Override
+ public boolean equals(final Object obj) {
+ if (!(obj instanceof DescriptorIntPair)) {
+ return false;
+ }
+ final DescriptorIntPair other = (DescriptorIntPair)obj;
return descriptor == other.descriptor && number == other.number;
}
}
diff --git a/java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java b/java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
new file mode 100644
index 00000000..d5288dd8
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
@@ -0,0 +1,169 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Equivalent to {@link ExtensionRegistry} but supports only "lite" types.
+ * <p>
+ * If all of your types are lite types, then you only need to use
+ * {@code ExtensionRegistryLite}. Similarly, if all your types are regular
+ * types, then you only need {@link ExtensionRegistry}. Typically it does not
+ * make sense to mix the two, since if you have any regular types in your
+ * program, you then require the full runtime and lose all the benefits of
+ * the lite runtime, so you might as well make all your types be regular types.
+ * However, in some cases (e.g. when depending on multiple third-patry libraries
+ * where one uses lite types and one uses regular), you may find yourself
+ * wanting to mix the two. In this case things get more complicated.
+ * <p>
+ * There are three factors to consider: Whether the type being extended is
+ * lite, whether the embedded type (in the case of a message-typed extension)
+ * is lite, and whether the extension itself is lite. Since all three are
+ * declared in different files, they could all be different. Here are all
+ * the combinations and which type of registry to use:
+ * <pre>
+ * Extended type Inner type Extension Use registry
+ * =======================================================================
+ * lite lite lite ExtensionRegistryLite
+ * lite regular lite ExtensionRegistry
+ * regular regular regular ExtensionRegistry
+ * all other combinations not supported
+ * </pre>
+ * <p>
+ * Note that just as regular types are not allowed to contain lite-type fields,
+ * they are also not allowed to contain lite-type extensions. This is because
+ * regular types must be fully accessible via reflection, which in turn means
+ * that all the inner messages must also support reflection. On the other hand,
+ * since regular types implement the entire lite interface, there is no problem
+ * with embedding regular types inside lite types.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class ExtensionRegistryLite {
+ /** Construct a new, empty instance. */
+ public static ExtensionRegistryLite newInstance() {
+ return new ExtensionRegistryLite();
+ }
+
+ /** Get the unmodifiable singleton empty instance. */
+ public static ExtensionRegistryLite getEmptyRegistry() {
+ return EMPTY;
+ }
+
+ /** Returns an unmodifiable view of the registry. */
+ public ExtensionRegistryLite getUnmodifiable() {
+ return new ExtensionRegistryLite(this);
+ }
+
+ /**
+ * Find an extension by containing type and field number.
+ *
+ * @return Information about the extension if found, or {@code null}
+ * otherwise.
+ */
+ @SuppressWarnings("unchecked")
+ public <ContainingType extends MessageLite>
+ GeneratedMessageLite.GeneratedExtension<ContainingType, ?>
+ findLiteExtensionByNumber(
+ final ContainingType containingTypeDefaultInstance,
+ final int fieldNumber) {
+ return (GeneratedMessageLite.GeneratedExtension<ContainingType, ?>)
+ extensionsByNumber.get(
+ new ObjectIntPair(containingTypeDefaultInstance, fieldNumber));
+ }
+
+ /** Add an extension from a lite generated file to the registry. */
+ public final void add(
+ final GeneratedMessageLite.GeneratedExtension<?, ?> extension) {
+ extensionsByNumber.put(
+ new ObjectIntPair(extension.getContainingTypeDefaultInstance(),
+ extension.getNumber()),
+ extension);
+ }
+
+ // =================================================================
+ // Private stuff.
+
+ // Constructors are package-private so that ExtensionRegistry can subclass
+ // this.
+
+ ExtensionRegistryLite() {
+ this.extensionsByNumber =
+ new HashMap<ObjectIntPair,
+ GeneratedMessageLite.GeneratedExtension<?, ?>>();
+ }
+
+ ExtensionRegistryLite(ExtensionRegistryLite other) {
+ if (other == EMPTY) {
+ this.extensionsByNumber = Collections.emptyMap();
+ } else {
+ this.extensionsByNumber =
+ Collections.unmodifiableMap(other.extensionsByNumber);
+ }
+ }
+
+ private final Map<ObjectIntPair,
+ GeneratedMessageLite.GeneratedExtension<?, ?>>
+ extensionsByNumber;
+
+ private ExtensionRegistryLite(boolean empty) {
+ this.extensionsByNumber = Collections.emptyMap();
+ }
+ private static final ExtensionRegistryLite EMPTY =
+ new ExtensionRegistryLite(true);
+
+ /** A (Object, int) pair, used as a map key. */
+ private static final class ObjectIntPair {
+ private final Object object;
+ private final int number;
+
+ ObjectIntPair(final Object object, final int number) {
+ this.object = object;
+ this.number = number;
+ }
+
+ @Override
+ public int hashCode() {
+ return System.identityHashCode(object) * ((1 << 16) - 1) + number;
+ }
+ @Override
+ public boolean equals(final Object obj) {
+ if (!(obj instanceof ObjectIntPair)) {
+ return false;
+ }
+ final ObjectIntPair other = (ObjectIntPair)obj;
+ return object == other.object && number == other.number;
+ }
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/FieldSet.java b/java/src/main/java/com/google/protobuf/FieldSet.java
index 01da3faf..93e55f29 100644
--- a/java/src/main/java/com/google/protobuf/FieldSet.java
+++ b/java/src/main/java/com/google/protobuf/FieldSet.java
@@ -30,16 +30,13 @@
package com.google.protobuf;
-import com.google.protobuf.Descriptors.Descriptor;
-import com.google.protobuf.Descriptors.FieldDescriptor;
-import com.google.protobuf.Descriptors.EnumValueDescriptor;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.TreeMap;
import java.util.List;
import java.util.Map;
+import java.io.IOException;
/**
* A class which represents an arbitrary set of fields of some message type.
@@ -49,43 +46,70 @@ import java.util.Map;
*
* @author kenton@google.com Kenton Varda
*/
-final class FieldSet {
- private Map<FieldDescriptor, Object> fields;
+final class FieldSet<FieldDescriptorType extends
+ FieldSet.FieldDescriptorLite<FieldDescriptorType>> {
+ /**
+ * Interface for a FieldDescriptor or lite extension descriptor. This
+ * prevents FieldSet from depending on {@link Descriptors.FieldDescriptor}.
+ */
+ public interface FieldDescriptorLite<T extends FieldDescriptorLite<T>>
+ extends Comparable<T> {
+ int getNumber();
+ WireFormat.FieldType getLiteType();
+ WireFormat.JavaType getLiteJavaType();
+ boolean isRepeated();
+ boolean isPacked();
+ Internal.EnumLiteMap<?> getEnumType();
+
+ // If getLiteJavaType() == MESSAGE, this merges a message object of the
+ // type into a builder of the type. Returns {@code to}.
+ MessageLite.Builder internalMergeFrom(
+ MessageLite.Builder to, MessageLite from);
+ }
+
+ private Map<FieldDescriptorType, Object> fields;
/** Construct a new FieldSet. */
private FieldSet() {
// Use a TreeMap because fields need to be in canonical order when
// serializing.
- this.fields = new TreeMap<FieldDescriptor, Object>();
+ // TODO(kenton): Maybe use some sort of sparse array instead? It would
+ // even make sense to store the first 16 or so tags in a flat array
+ // to make DynamicMessage faster.
+ fields = new TreeMap<FieldDescriptorType, Object>();
}
/**
- * Construct a new FieldSet with the given map. This is only used by
- * DEFAULT_INSTANCE, to pass in an immutable empty map.
+ * Construct an empty FieldSet. This is only used to initialize
+ * DEFAULT_INSTANCE.
*/
- private FieldSet(Map<FieldDescriptor, Object> fields) {
- this.fields = fields;
+ private FieldSet(final boolean dummy) {
+ this.fields = Collections.emptyMap();
}
/** Construct a new FieldSet. */
- public static FieldSet newFieldSet() {
- return new FieldSet();
+ public static <T extends FieldSet.FieldDescriptorLite<T>>
+ FieldSet<T> newFieldSet() {
+ return new FieldSet<T>();
}
/** Get an immutable empty FieldSet. */
- public static FieldSet emptySet() {
+ @SuppressWarnings("unchecked")
+ public static <T extends FieldSet.FieldDescriptorLite<T>>
+ FieldSet<T> emptySet() {
return DEFAULT_INSTANCE;
}
- private static final FieldSet DEFAULT_INSTANCE =
- new FieldSet(Collections.<FieldDescriptor, Object>emptyMap());
+ @SuppressWarnings("unchecked")
+ private static final FieldSet DEFAULT_INSTANCE = new FieldSet(true);
/** Make this FieldSet immutable from this point forward. */
@SuppressWarnings("unchecked")
public void makeImmutable() {
- for (Map.Entry<FieldDescriptor, Object> entry: fields.entrySet()) {
+ for (final Map.Entry<FieldDescriptorType, Object> entry:
+ fields.entrySet()) {
if (entry.getKey().isRepeated()) {
- List value = (List)entry.getValue();
- entry.setValue(Collections.unmodifiableList(value));
+ final List value = (List)entry.getValue();
+ fields.put(entry.getKey(), Collections.unmodifiableList(value));
}
}
fields = Collections.unmodifiableMap(fields);
@@ -98,56 +122,52 @@ final class FieldSet {
fields.clear();
}
- /** See {@link Message#getAllFields()}. */
- public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
+ /**
+ * Get a simple map containing all the fields.
+ */
+ public Map<FieldDescriptorType, Object> getAllFields() {
return Collections.unmodifiableMap(fields);
}
/**
- * Get an interator to the field map. This iterator should not be leaked
+ * Get an iterator to the field map. This iterator should not be leaked
* out of the protobuf library as it is not protected from mutation.
*/
- public Iterator<Map.Entry<Descriptors.FieldDescriptor, Object>> iterator() {
+ public Iterator<Map.Entry<FieldDescriptorType, Object>> iterator() {
return fields.entrySet().iterator();
}
- /** See {@link Message#hasField(Descriptors.FieldDescriptor)}. */
- public boolean hasField(Descriptors.FieldDescriptor field) {
- if (field.isRepeated()) {
+ /**
+ * Useful for implementing
+ * {@link Message#hasField(Descriptors.FieldDescriptor)}.
+ */
+ public boolean hasField(final FieldDescriptorType descriptor) {
+ if (descriptor.isRepeated()) {
throw new IllegalArgumentException(
"hasField() can only be called on non-repeated fields.");
}
- return fields.containsKey(field);
+ return fields.get(descriptor) != null;
}
/**
- * See {@link Message#getField(Descriptors.FieldDescriptor)}. This method
- * returns {@code null} if the field is a singular message type and is not
- * set; in this case it is up to the caller to fetch the message's default
- * instance.
+ * Useful for implementing
+ * {@link Message#getField(Descriptors.FieldDescriptor)}. This method
+ * returns {@code null} if the field is not set; in this case it is up
+ * to the caller to fetch the field's default value.
*/
- public Object getField(Descriptors.FieldDescriptor field) {
- Object result = fields.get(field);
- if (result == null) {
- if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
- if (field.isRepeated()) {
- return Collections.emptyList();
- } else {
- return null;
- }
- } else {
- return field.getDefaultValue();
- }
- } else {
- return result;
- }
+ public Object getField(final FieldDescriptorType descriptor) {
+ return fields.get(descriptor);
}
- /** See {@link Message.Builder#setField(Descriptors.FieldDescriptor,Object)}. */
+ /**
+ * Useful for implementing
+ * {@link Message.Builder#setField(Descriptors.FieldDescriptor,Object)}.
+ */
@SuppressWarnings("unchecked")
- public void setField(Descriptors.FieldDescriptor field, Object value) {
- if (field.isRepeated()) {
+ public void setField(final FieldDescriptorType descriptor,
+ Object value) {
+ if (descriptor.isRepeated()) {
if (!(value instanceof List)) {
throw new IllegalArgumentException(
"Wrong object type used with protocol message reflection.");
@@ -155,78 +175,108 @@ final class FieldSet {
// Wrap the contents in a new list so that the caller cannot change
// the list's contents after setting it.
- List newList = new ArrayList();
+ final List newList = new ArrayList();
newList.addAll((List)value);
- for (Object element : newList) {
- verifyType(field, element);
+ for (final Object element : newList) {
+ verifyType(descriptor.getLiteType(), element);
}
value = newList;
} else {
- verifyType(field, value);
+ verifyType(descriptor.getLiteType(), value);
}
- fields.put(field, value);
+ fields.put(descriptor, value);
}
- /** See {@link Message.Builder#clearField(Descriptors.FieldDescriptor)}. */
- public void clearField(Descriptors.FieldDescriptor field) {
- fields.remove(field);
+ /**
+ * Useful for implementing
+ * {@link Message.Builder#clearField(Descriptors.FieldDescriptor)}.
+ */
+ public void clearField(final FieldDescriptorType descriptor) {
+ fields.remove(descriptor);
}
- /** See {@link Message#getRepeatedFieldCount(Descriptors.FieldDescriptor)}. */
- public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) {
- if (!field.isRepeated()) {
+ /**
+ * Useful for implementing
+ * {@link Message#getRepeatedFieldCount(Descriptors.FieldDescriptor)}.
+ */
+ public int getRepeatedFieldCount(final FieldDescriptorType descriptor) {
+ if (!descriptor.isRepeated()) {
throw new IllegalArgumentException(
- "getRepeatedFieldCount() can only be called on repeated fields.");
+ "getRepeatedField() can only be called on repeated fields.");
}
- return ((List)getField(field)).size();
+ final Object value = fields.get(descriptor);
+ if (value == null) {
+ return 0;
+ } else {
+ return ((List) value).size();
+ }
}
- /** See {@link Message#getRepeatedField(Descriptors.FieldDescriptor,int)}. */
- public Object getRepeatedField(Descriptors.FieldDescriptor field, int index) {
- if (!field.isRepeated()) {
+ /**
+ * Useful for implementing
+ * {@link Message#getRepeatedField(Descriptors.FieldDescriptor,int)}.
+ */
+ public Object getRepeatedField(final FieldDescriptorType descriptor,
+ final int index) {
+ if (!descriptor.isRepeated()) {
throw new IllegalArgumentException(
"getRepeatedField() can only be called on repeated fields.");
}
- return ((List)getField(field)).get(index);
+ final Object value = fields.get(descriptor);
+
+ if (value == null) {
+ throw new IndexOutOfBoundsException();
+ } else {
+ return ((List) value).get(index);
+ }
}
- /** See {@link Message.Builder#setRepeatedField(Descriptors.FieldDescriptor,int,Object)}. */
+ /**
+ * Useful for implementing
+ * {@link Message.Builder#setRepeatedField(Descriptors.FieldDescriptor,int,Object)}.
+ */
@SuppressWarnings("unchecked")
- public void setRepeatedField(Descriptors.FieldDescriptor field, int index,
- Object value) {
- if (!field.isRepeated()) {
+ public void setRepeatedField(final FieldDescriptorType descriptor,
+ final int index,
+ final Object value) {
+ if (!descriptor.isRepeated()) {
throw new IllegalArgumentException(
- "setRepeatedField() can only be called on repeated fields.");
+ "getRepeatedField() can only be called on repeated fields.");
}
- verifyType(field, value);
-
- List list = (List)fields.get(field);
+ final Object list = fields.get(descriptor);
if (list == null) {
throw new IndexOutOfBoundsException();
}
- list.set(index, value);
+ verifyType(descriptor.getLiteType(), value);
+ ((List) list).set(index, value);
}
- /** See {@link Message.Builder#addRepeatedField(Descriptors.FieldDescriptor,Object)}. */
+ /**
+ * Useful for implementing
+ * {@link Message.Builder#addRepeatedField(Descriptors.FieldDescriptor,Object)}.
+ */
@SuppressWarnings("unchecked")
- public void addRepeatedField(Descriptors.FieldDescriptor field,
- Object value) {
- if (!field.isRepeated()) {
+ public void addRepeatedField(final FieldDescriptorType descriptor,
+ final Object value) {
+ if (!descriptor.isRepeated()) {
throw new IllegalArgumentException(
- "setRepeatedField() can only be called on repeated fields.");
+ "addRepeatedField() can only be called on repeated fields.");
}
- verifyType(field, value);
+ verifyType(descriptor.getLiteType(), value);
- List list = (List)fields.get(field);
- if (list == null) {
+ final Object existingValue = fields.get(descriptor);
+ List list;
+ if (existingValue == null) {
list = new ArrayList();
- fields.put(field, list);
+ fields.put(descriptor, list);
+ } else {
+ list = (List) existingValue;
}
list.add(value);
@@ -239,9 +289,14 @@ final class FieldSet {
*
* @throws IllegalArgumentException The value is not of the right type.
*/
- private void verifyType(FieldDescriptor field, Object value) {
+ private static void verifyType(final WireFormat.FieldType type,
+ final Object value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+
boolean isValid = false;
- switch (field.getJavaType()) {
+ switch (type.getJavaType()) {
case INT: isValid = value instanceof Integer ; break;
case LONG: isValid = value instanceof Long ; break;
case FLOAT: isValid = value instanceof Float ; break;
@@ -250,26 +305,25 @@ final class FieldSet {
case STRING: isValid = value instanceof String ; break;
case BYTE_STRING: isValid = value instanceof ByteString; break;
case ENUM:
- isValid = value instanceof EnumValueDescriptor &&
- ((EnumValueDescriptor)value).getType() == field.getEnumType();
+ // TODO(kenton): Caller must do type checking here, I guess.
+ isValid = value instanceof Internal.EnumLite;
break;
case MESSAGE:
- isValid = value instanceof Message &&
- ((Message)value).getDescriptorForType() == field.getMessageType();
+ // TODO(kenton): Caller must do type checking here, I guess.
+ isValid = value instanceof MessageLite;
break;
}
if (!isValid) {
- // When chaining calls to setField(), it can be hard to tell from
- // the stack trace which exact call failed, since the whole chain is
- // considered one line of code. So, let's make sure to include the
- // field name and other useful info in the exception.
+ // TODO(kenton): When chaining calls to setField(), it can be hard to
+ // tell from the stack trace which exact call failed, since the whole
+ // chain is considered one line of code. It would be nice to print
+ // more information here, e.g. naming the field. We used to do that.
+ // But we can't now that FieldSet doesn't use descriptors. Maybe this
+ // isn't a big deal, though, since it would only really apply when using
+ // reflection and generally people don't chain reflection setters.
throw new IllegalArgumentException(
- "Wrong object type used with protocol message reflection. " +
- "Message type \"" + field.getContainingType().getFullName() +
- "\", field \"" +
- (field.isExtension() ? field.getFullName() : field.getName()) +
- "\", value was type \"" + value.getClass().getName() + "\".");
+ "Wrong object type used with protocol message reflection.");
}
}
@@ -284,17 +338,19 @@ final class FieldSet {
*/
@SuppressWarnings("unchecked")
public boolean isInitialized() {
- for (Map.Entry<FieldDescriptor, Object> entry : fields.entrySet()) {
- FieldDescriptor field = entry.getKey();
- if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
- if (field.isRepeated()) {
- for (Message element : (List<Message>) entry.getValue()) {
+ for (final Map.Entry<FieldDescriptorType, Object> entry:
+ fields.entrySet()) {
+ final FieldDescriptorType descriptor = entry.getKey();
+ if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) {
+ if (descriptor.isRepeated()) {
+ for (final MessageLite element:
+ (List<MessageLite>) entry.getValue()) {
if (!element.isInitialized()) {
return false;
}
}
} else {
- if (!((Message) entry.getValue()).isInitialized()) {
+ if (!((MessageLite) entry.getValue()).isInitialized()) {
return false;
}
}
@@ -305,59 +361,17 @@ final class FieldSet {
}
/**
- * Like {@link #isInitialized()}, but also checks for the presence of
- * all required fields in the given type.
+ * Given a field type, return the wire type.
+ *
+ * @returns One of the {@code WIRETYPE_} constants defined in
+ * {@link WireFormat}.
*/
- @SuppressWarnings("unchecked")
- public boolean isInitialized(Descriptor type) {
- // Check that all required fields are present.
- for (FieldDescriptor field : type.getFields()) {
- if (field.isRequired()) {
- if (!hasField(field)) {
- return false;
- }
- }
- }
-
- // Check that embedded messages are initialized.
- return isInitialized();
- }
-
- /** See {@link Message.Builder#mergeFrom(Message)}. */
- @SuppressWarnings("unchecked")
- public void mergeFrom(Message other) {
- // Note: We don't attempt to verify that other's fields have valid
- // types. Doing so would be a losing battle. We'd have to verify
- // all sub-messages as well, and we'd have to make copies of all of
- // them to insure that they don't change after verification (since
- // the Message interface itself cannot enforce immutability of
- // implementations).
- // TODO(kenton): Provide a function somewhere called makeDeepCopy()
- // which allows people to make secure deep copies of messages.
-
- for (Map.Entry<FieldDescriptor, Object> entry :
- other.getAllFields().entrySet()) {
- FieldDescriptor field = entry.getKey();
- if (field.isRepeated()) {
- List existingValue = (List)fields.get(field);
- if (existingValue == null) {
- existingValue = new ArrayList();
- fields.put(field, existingValue);
- }
- existingValue.addAll((List)entry.getValue());
- } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
- Message existingValue = (Message)fields.get(field);
- if (existingValue == null) {
- setField(field, entry.getValue());
- } else {
- setField(field,
- existingValue.toBuilder()
- .mergeFrom((Message)entry.getValue())
- .build());
- }
- } else {
- setField(field, entry.getValue());
- }
+ static int getWireFormatForFieldType(final WireFormat.FieldType type,
+ boolean isPacked) {
+ if (isPacked) {
+ return WireFormat.WIRETYPE_LENGTH_DELIMITED;
+ } else {
+ return type.getWireType();
}
}
@@ -365,360 +379,334 @@ final class FieldSet {
* Like {@link #mergeFrom(Message)}, but merges from another {@link FieldSet}.
*/
@SuppressWarnings("unchecked")
- public void mergeFrom(FieldSet other) {
- for (Map.Entry<FieldDescriptor, Object> entry : other.fields.entrySet()) {
- FieldDescriptor field = entry.getKey();
- Object value = entry.getValue();
-
- if (field.isRepeated()) {
- List existingValue = (List)fields.get(field);
- if (existingValue == null) {
- existingValue = new ArrayList();
- fields.put(field, existingValue);
+ public void mergeFrom(final FieldSet<FieldDescriptorType> other) {
+ for (final Map.Entry<FieldDescriptorType, Object> entry:
+ other.fields.entrySet()) {
+ final FieldDescriptorType descriptor = entry.getKey();
+ final Object otherValue = entry.getValue();
+
+ if (descriptor.isRepeated()) {
+ Object value = fields.get(descriptor);
+ if (value == null) {
+ // Our list is empty, but we still need to make a defensive copy of
+ // the other list since we don't know if the other FieldSet is still
+ // mutable.
+ fields.put(descriptor, new ArrayList((List) otherValue));
+ } else {
+ // Concatenate the lists.
+ ((List) value).addAll((List) otherValue);
}
- existingValue.addAll((List)value);
- } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
- Message existingValue = (Message)fields.get(field);
- if (existingValue == null) {
- setField(field, value);
+ } else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) {
+ Object value = fields.get(descriptor);
+ if (value == null) {
+ fields.put(descriptor, otherValue);
} else {
- setField(field,
- existingValue.toBuilder()
- .mergeFrom((Message)value)
+ // Merge the messages.
+ fields.put(descriptor,
+ descriptor.internalMergeFrom(
+ ((MessageLite) value).toBuilder(), (MessageLite) otherValue)
.build());
}
+
} else {
- setField(field, value);
+ fields.put(descriptor, otherValue);
}
}
}
- // TODO(kenton): Move parsing code into AbstractMessage, since it no longer
- // uses any special knowledge from FieldSet.
+ // TODO(kenton): Move static parsing and serialization methods into some
+ // other class. Probably WireFormat.
/**
- * See {@link Message.Builder#mergeFrom(CodedInputStream)}.
- * @param builder The {@code Builder} for the target message.
+ * Read a field of any primitive type from a CodedInputStream. Enums,
+ * groups, and embedded messages are not handled by this method.
+ *
+ * @param input The stream from which to read.
+ * @param type Declared type of the field.
+ * @return An object representing the field's value, of the exact
+ * type which would be returned by
+ * {@link Message#getField(Descriptors.FieldDescriptor)} for
+ * this field.
*/
- public static void mergeFrom(CodedInputStream input,
- UnknownFieldSet.Builder unknownFields,
- ExtensionRegistry extensionRegistry,
- Message.Builder builder)
- throws java.io.IOException {
- while (true) {
- int tag = input.readTag();
- if (tag == 0) {
- break;
- }
+ public static Object readPrimitiveField(
+ CodedInputStream input,
+ final WireFormat.FieldType type) throws IOException {
+ switch (type) {
+ case DOUBLE : return input.readDouble ();
+ case FLOAT : return input.readFloat ();
+ case INT64 : return input.readInt64 ();
+ case UINT64 : return input.readUInt64 ();
+ case INT32 : return input.readInt32 ();
+ case FIXED64 : return input.readFixed64 ();
+ case FIXED32 : return input.readFixed32 ();
+ case BOOL : return input.readBool ();
+ case STRING : return input.readString ();
+ case BYTES : return input.readBytes ();
+ case UINT32 : return input.readUInt32 ();
+ case SFIXED32: return input.readSFixed32();
+ case SFIXED64: return input.readSFixed64();
+ case SINT32 : return input.readSInt32 ();
+ case SINT64 : return input.readSInt64 ();
+
+ case GROUP:
+ throw new IllegalArgumentException(
+ "readPrimitiveField() cannot handle nested groups.");
+ case MESSAGE:
+ throw new IllegalArgumentException(
+ "readPrimitiveField() cannot handle embedded messages.");
+ case ENUM:
+ // We don't handle enums because we don't know what to do if the
+ // value is not recognized.
+ throw new IllegalArgumentException(
+ "readPrimitiveField() cannot handle enums.");
+ }
- if (!mergeFieldFrom(input, unknownFields, extensionRegistry,
- builder, tag)) {
- // end group tag
- break;
- }
+ throw new RuntimeException(
+ "There is no way to get here, but the compiler thinks otherwise.");
+ }
+
+ /** See {@link Message#writeTo(CodedOutputStream)}. */
+ public void writeTo(final CodedOutputStream output)
+ throws IOException {
+ for (final Map.Entry<FieldDescriptorType, Object> entry:
+ fields.entrySet()) {
+ writeField(entry.getKey(), entry.getValue(), output);
}
}
/**
- * Like {@link #mergeFrom(CodedInputStream, UnknownFieldSet.Builder,
- * ExtensionRegistry, Message.Builder)}, but parses a single field.
- * @param tag The tag, which should have already been read.
- * @return {@code true} unless the tag is an end-group tag.
+ * Like {@link #writeTo} but uses MessageSet wire format.
*/
- @SuppressWarnings("unchecked")
- public static boolean mergeFieldFrom(
- CodedInputStream input,
- UnknownFieldSet.Builder unknownFields,
- ExtensionRegistry extensionRegistry,
- Message.Builder builder,
- int tag) throws java.io.IOException {
- Descriptor type = builder.getDescriptorForType();
-
- if (type.getOptions().getMessageSetWireFormat() &&
- tag == WireFormat.MESSAGE_SET_ITEM_TAG) {
- mergeMessageSetExtensionFromCodedStream(
- input, unknownFields, extensionRegistry, builder);
- return true;
- }
-
- int wireType = WireFormat.getTagWireType(tag);
- int fieldNumber = WireFormat.getTagFieldNumber(tag);
-
- FieldDescriptor field;
- Message defaultInstance = null;
-
- if (type.isExtensionNumber(fieldNumber)) {
- ExtensionRegistry.ExtensionInfo extension =
- extensionRegistry.findExtensionByNumber(type, fieldNumber);
- if (extension == null) {
- field = null;
+ public void writeMessageSetTo(final CodedOutputStream output)
+ throws IOException {
+ for (final Map.Entry<FieldDescriptorType, Object> entry:
+ fields.entrySet()) {
+ final FieldDescriptorType descriptor = entry.getKey();
+ if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE &&
+ !descriptor.isRepeated() && !descriptor.isPacked()) {
+ output.writeMessageSetExtension(entry.getKey().getNumber(),
+ (MessageLite) entry.getValue());
} else {
- field = extension.descriptor;
- defaultInstance = extension.defaultInstance;
+ writeField(descriptor, entry.getValue(), output);
}
- } else {
- field = type.findFieldByNumber(fieldNumber);
}
+ }
- if (field == null ||
- wireType != WireFormat.getWireFormatForField(field)) {
- // Unknown field or wrong wire type. Skip.
- return unknownFields.mergeFieldFrom(tag, input);
+ /**
+ * Write a single tag-value pair to the stream.
+ *
+ * @param output The output stream.
+ * @param type The field's type.
+ * @param number The field's number.
+ * @param value Object representing the field's value. Must be of the exact
+ * type which would be returned by
+ * {@link Message#getField(Descriptors.FieldDescriptor)} for
+ * this field.
+ */
+ private static void writeElement(final CodedOutputStream output,
+ final WireFormat.FieldType type,
+ final int number,
+ final Object value) throws IOException {
+ // Special case for groups, which need a start and end tag; other fields
+ // can just use writeTag() and writeFieldNoTag().
+ if (type == WireFormat.FieldType.GROUP) {
+ output.writeGroup(number, (MessageLite) value);
} else {
- if (field.getOptions().getPacked()) {
- int length = input.readRawVarint32();
- int limit = input.pushLimit(length);
- if (field.getType() == FieldDescriptor.Type.ENUM) {
- while (input.getBytesUntilLimit() > 0) {
- int rawValue = input.readEnum();
- Object value = field.getEnumType().findValueByNumber(rawValue);
- if (value == null) {
- // If the number isn't recognized as a valid value for this
- // enum, drop it (don't even add it to unknownFields).
- return true;
- }
- builder.addRepeatedField(field, value);
- }
- } else {
- while (input.getBytesUntilLimit() > 0) {
- Object value = input.readPrimitiveField(field.getType());
- builder.addRepeatedField(field, value);
- }
- }
- input.popLimit(limit);
- } else {
- Object value;
- switch (field.getType()) {
- case GROUP: {
- Message.Builder subBuilder;
- if (defaultInstance != null) {
- subBuilder = defaultInstance.newBuilderForType();
- } else {
- subBuilder = builder.newBuilderForField(field);
- }
- if (!field.isRepeated()) {
- subBuilder.mergeFrom((Message) builder.getField(field));
- }
- input.readGroup(field.getNumber(), subBuilder, extensionRegistry);
- value = subBuilder.build();
- break;
- }
- case MESSAGE: {
- Message.Builder subBuilder;
- if (defaultInstance != null) {
- subBuilder = defaultInstance.newBuilderForType();
- } else {
- subBuilder = builder.newBuilderForField(field);
- }
- if (!field.isRepeated()) {
- subBuilder.mergeFrom((Message) builder.getField(field));
- }
- input.readMessage(subBuilder, extensionRegistry);
- value = subBuilder.build();
- break;
- }
- case ENUM: {
- int rawValue = input.readEnum();
- value = field.getEnumType().findValueByNumber(rawValue);
- // If the number isn't recognized as a valid value for this enum,
- // drop it.
- if (value == null) {
- unknownFields.mergeVarintField(fieldNumber, rawValue);
- return true;
- }
- break;
- }
- default:
- value = input.readPrimitiveField(field.getType());
- break;
- }
-
- if (field.isRepeated()) {
- builder.addRepeatedField(field, value);
- } else {
- builder.setField(field, value);
- }
- }
+ output.writeTag(number, getWireFormatForFieldType(type, false));
+ writeElementNoTag(output, type, value);
}
-
- return true;
}
- /** Called by {@code #mergeFieldFrom()} to parse a MessageSet extension. */
- private static void mergeMessageSetExtensionFromCodedStream(
- CodedInputStream input,
- UnknownFieldSet.Builder unknownFields,
- ExtensionRegistry extensionRegistry,
- Message.Builder builder) throws java.io.IOException {
- Descriptor type = builder.getDescriptorForType();
-
- // The wire format for MessageSet is:
- // message MessageSet {
- // repeated group Item = 1 {
- // required int32 typeId = 2;
- // required bytes message = 3;
- // }
- // }
- // "typeId" is the extension's field number. The extension can only be
- // a message type, where "message" contains the encoded bytes of that
- // message.
- //
- // In practice, we will probably never see a MessageSet item in which
- // the message appears before the type ID, or where either field does not
- // appear exactly once. However, in theory such cases are valid, so we
- // should be prepared to accept them.
-
- int typeId = 0;
- ByteString rawBytes = null; // If we encounter "message" before "typeId"
- Message.Builder subBuilder = null;
- FieldDescriptor field = null;
-
- while (true) {
- int tag = input.readTag();
- if (tag == 0) {
+ /**
+ * Write a field of arbitrary type, without its tag, to the stream.
+ *
+ * @param output The output stream.
+ * @param type The field's type.
+ * @param value Object representing the field's value. Must be of the exact
+ * type which would be returned by
+ * {@link Message#getField(Descriptors.FieldDescriptor)} for
+ * this field.
+ */
+ private static void writeElementNoTag(
+ final CodedOutputStream output,
+ final WireFormat.FieldType type,
+ final Object value) throws IOException {
+ switch (type) {
+ case DOUBLE : output.writeDoubleNoTag ((Double ) value); break;
+ case FLOAT : output.writeFloatNoTag ((Float ) value); break;
+ case INT64 : output.writeInt64NoTag ((Long ) value); break;
+ case UINT64 : output.writeUInt64NoTag ((Long ) value); break;
+ case INT32 : output.writeInt32NoTag ((Integer ) value); break;
+ case FIXED64 : output.writeFixed64NoTag ((Long ) value); break;
+ case FIXED32 : output.writeFixed32NoTag ((Integer ) value); break;
+ case BOOL : output.writeBoolNoTag ((Boolean ) value); break;
+ case STRING : output.writeStringNoTag ((String ) value); break;
+ case GROUP : output.writeGroupNoTag ((MessageLite) value); break;
+ case MESSAGE : output.writeMessageNoTag ((MessageLite) value); break;
+ case BYTES : output.writeBytesNoTag ((ByteString ) value); break;
+ case UINT32 : output.writeUInt32NoTag ((Integer ) value); break;
+ case SFIXED32: output.writeSFixed32NoTag((Integer ) value); break;
+ case SFIXED64: output.writeSFixed64NoTag((Long ) value); break;
+ case SINT32 : output.writeSInt32NoTag ((Integer ) value); break;
+ case SINT64 : output.writeSInt64NoTag ((Long ) value); break;
+
+ case ENUM:
+ output.writeEnumNoTag(((Internal.EnumLite) value).getNumber());
break;
- }
+ }
+ }
- if (tag == WireFormat.MESSAGE_SET_TYPE_ID_TAG) {
- typeId = input.readUInt32();
- // Zero is not a valid type ID.
- if (typeId != 0) {
- ExtensionRegistry.ExtensionInfo extension =
- extensionRegistry.findExtensionByNumber(type, typeId);
- if (extension != null) {
- field = extension.descriptor;
- subBuilder = extension.defaultInstance.newBuilderForType();
- Message originalMessage = (Message)builder.getField(field);
- if (originalMessage != null) {
- subBuilder.mergeFrom(originalMessage);
- }
- if (rawBytes != null) {
- // We already encountered the message. Parse it now.
- subBuilder.mergeFrom(
- CodedInputStream.newInstance(rawBytes.newInput()));
- rawBytes = null;
- }
- } else {
- // Unknown extension number. If we already saw data, put it
- // in rawBytes.
- if (rawBytes != null) {
- unknownFields.mergeField(typeId,
- UnknownFieldSet.Field.newBuilder()
- .addLengthDelimited(rawBytes)
- .build());
- rawBytes = null;
- }
- }
+ /** Write a single field. */
+ public static void writeField(final FieldDescriptorLite<?> descriptor,
+ final Object value,
+ final CodedOutputStream output)
+ throws IOException {
+ WireFormat.FieldType type = descriptor.getLiteType();
+ int number = descriptor.getNumber();
+ if (descriptor.isRepeated()) {
+ final List valueList = (List)value;
+ if (descriptor.isPacked()) {
+ output.writeTag(number, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ // Compute the total data size so the length can be written.
+ int dataSize = 0;
+ for (final Object element : valueList) {
+ dataSize += computeElementSizeNoTag(type, element);
}
- } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) {
- if (typeId == 0) {
- // We haven't seen a type ID yet, so we have to store the raw bytes
- // for now.
- rawBytes = input.readBytes();
- } else if (subBuilder == null) {
- // We don't know how to parse this. Ignore it.
- unknownFields.mergeField(typeId,
- UnknownFieldSet.Field.newBuilder()
- .addLengthDelimited(input.readBytes())
- .build());
- } else {
- // We already know the type, so we can parse directly from the input
- // with no copying. Hooray!
- input.readMessage(subBuilder, extensionRegistry);
+ output.writeRawVarint32(dataSize);
+ // Write the data itself, without any tags.
+ for (final Object element : valueList) {
+ writeElementNoTag(output, type, element);
}
} else {
- // Unknown tag. Skip it.
- if (!input.skipField(tag)) {
- break; // end of group
+ for (final Object element : valueList) {
+ writeElement(output, type, number, element);
}
}
- }
-
- input.checkLastTagWas(WireFormat.MESSAGE_SET_ITEM_END_TAG);
-
- if (subBuilder != null) {
- builder.setField(field, subBuilder.build());
+ } else {
+ writeElement(output, type, number, value);
}
}
- /** See {@link Message#writeTo(CodedOutputStream)}. */
- public void writeTo(CodedOutputStream output)
- throws java.io.IOException {
- for (Map.Entry<FieldDescriptor, Object> entry : fields.entrySet()) {
- writeField(entry.getKey(), entry.getValue(), output);
+ /**
+ * See {@link Message#getSerializedSize()}. It's up to the caller to cache
+ * the resulting size if desired.
+ */
+ public int getSerializedSize() {
+ int size = 0;
+ for (final Map.Entry<FieldDescriptorType, Object> entry:
+ fields.entrySet()) {
+ size += computeFieldSize(entry.getKey(), entry.getValue());
}
+ return size;
}
- /** Write a single field. */
- public void writeField(FieldDescriptor field, Object value,
- CodedOutputStream output) throws java.io.IOException {
- if (field.isExtension() &&
- field.getContainingType().getOptions().getMessageSetWireFormat()) {
- output.writeMessageSetExtension(field.getNumber(), (Message)value);
- } else {
- if (field.isRepeated()) {
- List valueList = (List)value;
- if (field.getOptions().getPacked()) {
- output.writeTag(field.getNumber(),
- WireFormat.WIRETYPE_LENGTH_DELIMITED);
- // Compute the total data size so the length can be written.
- int dataSize = 0;
- for (Object element : valueList) {
- dataSize += output.computeFieldSizeNoTag(field.getType(), element);
- }
- output.writeRawVarint32(dataSize);
- // Write the data itself, without any tags.
- for (Object element : valueList) {
- output.writeFieldNoTag(field.getType(), element);
- }
- } else {
- for (Object element : valueList) {
- output.writeField(field.getType(), field.getNumber(), element);
- }
- }
+ /**
+ * Like {@link #getSerializedSize} but uses MessageSet wire format.
+ */
+ public int getMessageSetSerializedSize() {
+ int size = 0;
+ for (final Map.Entry<FieldDescriptorType, Object> entry:
+ fields.entrySet()) {
+ final FieldDescriptorType descriptor = entry.getKey();
+ if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE &&
+ !descriptor.isRepeated() && !descriptor.isPacked()) {
+ size += CodedOutputStream.computeMessageSetExtensionSize(
+ entry.getKey().getNumber(), (MessageLite) entry.getValue());
} else {
- output.writeField(field.getType(), field.getNumber(), value);
+ size += computeFieldSize(descriptor, entry.getValue());
}
}
+ return size;
}
/**
- * See {@link Message#getSerializedSize()}. It's up to the caller to cache
- * the resulting size if desired.
+ * Compute the number of bytes that would be needed to encode a
+ * single tag/value pair of arbitrary type.
+ *
+ * @param type The field's type.
+ * @param number The field's number.
+ * @param value Object representing the field's value. Must be of the exact
+ * type which would be returned by
+ * {@link Message#getField(Descriptors.FieldDescriptor)} for
+ * this field.
*/
- public int getSerializedSize() {
- int size = 0;
- for (Map.Entry<FieldDescriptor, Object> entry : fields.entrySet()) {
- FieldDescriptor field = entry.getKey();
- Object value = entry.getValue();
+ private static int computeElementSize(
+ final WireFormat.FieldType type,
+ final int number, final Object value) {
+ int tagSize = CodedOutputStream.computeTagSize(number);
+ if (type == WireFormat.FieldType.GROUP) {
+ tagSize *= 2;
+ }
+ return tagSize + computeElementSizeNoTag(type, value);
+ }
- if (field.isExtension() &&
- field.getContainingType().getOptions().getMessageSetWireFormat()) {
- size += CodedOutputStream.computeMessageSetExtensionSize(
- field.getNumber(), (Message) value);
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * particular value of arbitrary type, excluding tag.
+ *
+ * @param type The field's type.
+ * @param value Object representing the field's value. Must be of the exact
+ * type which would be returned by
+ * {@link Message#getField(Descriptors.FieldDescriptor)} for
+ * this field.
+ */
+ private static int computeElementSizeNoTag(
+ final WireFormat.FieldType type, final Object value) {
+ switch (type) {
+ // Note: Minor violation of 80-char limit rule here because this would
+ // actually be harder to read if we wrapped the lines.
+ case DOUBLE : return CodedOutputStream.computeDoubleSizeNoTag ((Double )value);
+ case FLOAT : return CodedOutputStream.computeFloatSizeNoTag ((Float )value);
+ case INT64 : return CodedOutputStream.computeInt64SizeNoTag ((Long )value);
+ case UINT64 : return CodedOutputStream.computeUInt64SizeNoTag ((Long )value);
+ case INT32 : return CodedOutputStream.computeInt32SizeNoTag ((Integer )value);
+ case FIXED64 : return CodedOutputStream.computeFixed64SizeNoTag ((Long )value);
+ case FIXED32 : return CodedOutputStream.computeFixed32SizeNoTag ((Integer )value);
+ case BOOL : return CodedOutputStream.computeBoolSizeNoTag ((Boolean )value);
+ case STRING : return CodedOutputStream.computeStringSizeNoTag ((String )value);
+ case GROUP : return CodedOutputStream.computeGroupSizeNoTag ((MessageLite)value);
+ case MESSAGE : return CodedOutputStream.computeMessageSizeNoTag ((MessageLite)value);
+ case BYTES : return CodedOutputStream.computeBytesSizeNoTag ((ByteString )value);
+ case UINT32 : return CodedOutputStream.computeUInt32SizeNoTag ((Integer )value);
+ case SFIXED32: return CodedOutputStream.computeSFixed32SizeNoTag((Integer )value);
+ case SFIXED64: return CodedOutputStream.computeSFixed64SizeNoTag((Long )value);
+ case SINT32 : return CodedOutputStream.computeSInt32SizeNoTag ((Integer )value);
+ case SINT64 : return CodedOutputStream.computeSInt64SizeNoTag ((Long )value);
+
+ case ENUM:
+ return CodedOutputStream.computeEnumSizeNoTag(
+ ((Internal.EnumLite) value).getNumber());
+ }
+
+ throw new RuntimeException(
+ "There is no way to get here, but the compiler thinks otherwise.");
+ }
+
+ /**
+ * Compute the number of bytes needed to encode a particular field.
+ */
+ public static int computeFieldSize(final FieldDescriptorLite<?> descriptor,
+ final Object value) {
+ WireFormat.FieldType type = descriptor.getLiteType();
+ int number = descriptor.getNumber();
+ if (descriptor.isRepeated()) {
+ if (descriptor.isPacked()) {
+ int dataSize = 0;
+ for (final Object element : (List)value) {
+ dataSize += computeElementSizeNoTag(type, element);
+ }
+ return dataSize +
+ CodedOutputStream.computeTagSize(number) +
+ CodedOutputStream.computeRawVarint32Size(dataSize);
} else {
- if (field.isRepeated()) {
- if (field.getOptions().getPacked()) {
- int dataSize = 0;
- for (Object element : (List)value) {
- dataSize += CodedOutputStream.computeFieldSizeNoTag(
- field.getType(), element);
- }
- size += dataSize +
- CodedOutputStream.computeTagSize(field.getNumber()) +
- CodedOutputStream.computeRawVarint32Size(dataSize);
- } else {
- for (Object element : (List)value) {
- size += CodedOutputStream.computeFieldSize(
- field.getType(), field.getNumber(), element);
- }
- }
- } else {
- size += CodedOutputStream.computeFieldSize(
- field.getType(), field.getNumber(), value);
+ int size = 0;
+ for (final Object element : (List)value) {
+ size += computeElementSize(type, number, element);
}
+ return size;
}
+ } else {
+ return computeElementSize(type, number, value);
}
- return size;
}
}
diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessage.java b/java/src/main/java/com/google/protobuf/GeneratedMessage.java
index 77c88c30..4994faad 100644
--- a/java/src/main/java/com/google/protobuf/GeneratedMessage.java
+++ b/java/src/main/java/com/google/protobuf/GeneratedMessage.java
@@ -36,8 +36,8 @@ import com.google.protobuf.Descriptors.FieldDescriptor;
import java.io.IOException;
import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@@ -69,13 +69,13 @@ public abstract class GeneratedMessage extends AbstractMessage {
}
/** Internal helper which returns a mutable map. */
- private final Map<FieldDescriptor, Object> getAllFieldsMutable() {
- TreeMap<FieldDescriptor, Object> result =
+ private Map<FieldDescriptor, Object> getAllFieldsMutable() {
+ final TreeMap<FieldDescriptor, Object> result =
new TreeMap<FieldDescriptor, Object>();
- Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
- for (FieldDescriptor field : descriptor.getFields()) {
+ final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
+ for (final FieldDescriptor field : descriptor.getFields()) {
if (field.isRepeated()) {
- List value = (List) getField(field);
+ final List value = (List) getField(field);
if (!value.isEmpty()) {
result.put(field, value);
}
@@ -88,8 +88,9 @@ public abstract class GeneratedMessage extends AbstractMessage {
return result;
}
+ @Override
public boolean isInitialized() {
- for (FieldDescriptor field : getDescriptorForType().getFields()) {
+ for (final FieldDescriptor field : getDescriptorForType().getFields()) {
// Check that all required fields are present.
if (field.isRequired()) {
if (!hasField(field)) {
@@ -99,9 +100,9 @@ public abstract class GeneratedMessage extends AbstractMessage {
// Check that embedded messages are initialized.
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
if (field.isRepeated()) {
- @SuppressWarnings("unchecked")
+ @SuppressWarnings("unchecked") final
List<Message> messageList = (List<Message>) getField(field);
- for (Message element : messageList) {
+ for (final Message element : messageList) {
if (!element.isInitialized()) {
return false;
}
@@ -121,20 +122,20 @@ public abstract class GeneratedMessage extends AbstractMessage {
return Collections.unmodifiableMap(getAllFieldsMutable());
}
- public boolean hasField(Descriptors.FieldDescriptor field) {
+ public boolean hasField(final FieldDescriptor field) {
return internalGetFieldAccessorTable().getField(field).has(this);
}
- public Object getField(FieldDescriptor field) {
+ public Object getField(final FieldDescriptor field) {
return internalGetFieldAccessorTable().getField(field).get(this);
}
- public int getRepeatedFieldCount(FieldDescriptor field) {
+ public int getRepeatedFieldCount(final FieldDescriptor field) {
return internalGetFieldAccessorTable().getField(field)
.getRepeatedCount(this);
}
- public Object getRepeatedField(FieldDescriptor field, int index) {
+ public Object getRepeatedField(final FieldDescriptor field, final int index) {
return internalGetFieldAccessorTable().getField(field)
.getRepeated(this, index);
}
@@ -148,6 +149,15 @@ public abstract class GeneratedMessage extends AbstractMessage {
extends AbstractMessage.Builder<BuilderType> {
protected Builder() {}
+ // This is implemented here only to work around an apparent bug in the
+ // Java compiler and/or build system. See bug #1898463. The mere presence
+ // of this dummy clone() implementation makes it go away.
+ @Override
+ public BuilderType clone() {
+ throw new UnsupportedOperationException(
+ "This is supposed to be overridden by subclasses.");
+ }
+
/**
* Get the message being built. We don't just pass this to the
* constructor because it becomes null when build() is called.
@@ -163,55 +173,24 @@ public abstract class GeneratedMessage extends AbstractMessage {
return internalGetResult().internalGetFieldAccessorTable();
}
- public BuilderType mergeFrom(Message other) {
- if (other.getDescriptorForType() !=
- internalGetFieldAccessorTable().descriptor) {
- throw new IllegalArgumentException("Message type mismatch.");
- }
-
- for (Map.Entry<FieldDescriptor, Object> entry :
- other.getAllFields().entrySet()) {
- FieldDescriptor field = entry.getKey();
- if (field.isRepeated()) {
- // Concatenate repeated fields.
- for (Object element : (List) entry.getValue()) {
- addRepeatedField(field, element);
- }
- } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE &&
- hasField(field)) {
- // Merge singular embedded messages.
- Message oldValue = (Message) getField(field);
- setField(field,
- oldValue.newBuilderForType()
- .mergeFrom(oldValue)
- .mergeFrom((Message) entry.getValue())
- .buildPartial());
- } else {
- // Just overwrite.
- setField(field, entry.getValue());
- }
- }
- return (BuilderType) this;
- }
-
public Descriptor getDescriptorForType() {
return internalGetFieldAccessorTable().descriptor;
}
- public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
+ public Map<FieldDescriptor, Object> getAllFields() {
return internalGetResult().getAllFields();
}
public Message.Builder newBuilderForField(
- Descriptors.FieldDescriptor field) {
+ final FieldDescriptor field) {
return internalGetFieldAccessorTable().getField(field).newBuilder();
}
- public boolean hasField(Descriptors.FieldDescriptor field) {
+ public boolean hasField(final FieldDescriptor field) {
return internalGetResult().hasField(field);
}
- public Object getField(Descriptors.FieldDescriptor field) {
+ public Object getField(final FieldDescriptor field) {
if (field.isRepeated()) {
// The underlying list object is still modifiable at this point.
// Make sure not to expose the modifiable list to the caller.
@@ -222,35 +201,35 @@ public abstract class GeneratedMessage extends AbstractMessage {
}
}
- public BuilderType setField(Descriptors.FieldDescriptor field,
- Object value) {
+ public BuilderType setField(final FieldDescriptor field,
+ final Object value) {
internalGetFieldAccessorTable().getField(field).set(this, value);
return (BuilderType) this;
}
- public BuilderType clearField(Descriptors.FieldDescriptor field) {
+ public BuilderType clearField(final FieldDescriptor field) {
internalGetFieldAccessorTable().getField(field).clear(this);
return (BuilderType) this;
}
- public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) {
+ public int getRepeatedFieldCount(final FieldDescriptor field) {
return internalGetResult().getRepeatedFieldCount(field);
}
- public Object getRepeatedField(Descriptors.FieldDescriptor field,
- int index) {
+ public Object getRepeatedField(final FieldDescriptor field,
+ final int index) {
return internalGetResult().getRepeatedField(field, index);
}
- public BuilderType setRepeatedField(Descriptors.FieldDescriptor field,
- int index, Object value) {
+ 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(Descriptors.FieldDescriptor field,
- Object value) {
+ public BuilderType addRepeatedField(final FieldDescriptor field,
+ final Object value) {
internalGetFieldAccessorTable().getField(field).addRepeated(this, value);
return (BuilderType) this;
}
@@ -259,13 +238,16 @@ public abstract class GeneratedMessage extends AbstractMessage {
return internalGetResult().unknownFields;
}
- public final BuilderType setUnknownFields(UnknownFieldSet unknownFields) {
+ public final BuilderType setUnknownFields(
+ final UnknownFieldSet unknownFields) {
internalGetResult().unknownFields = unknownFields;
return (BuilderType) this;
}
- public final BuilderType mergeUnknownFields(UnknownFieldSet unknownFields) {
- GeneratedMessage result = internalGetResult();
+ @Override
+ public final BuilderType mergeUnknownFields(
+ final UnknownFieldSet unknownFields) {
+ final GeneratedMessage result = internalGetResult();
result.unknownFields =
UnknownFieldSet.newBuilder(result.unknownFields)
.mergeFrom(unknownFields)
@@ -281,36 +263,13 @@ public abstract class GeneratedMessage extends AbstractMessage {
* Called by subclasses to parse an unknown field.
* @return {@code true} unless the tag is an end-group tag.
*/
- protected boolean parseUnknownField(CodedInputStream input,
- UnknownFieldSet.Builder unknownFields,
- ExtensionRegistry extensionRegistry,
- int tag)
- throws IOException {
+ protected boolean parseUnknownField(
+ final CodedInputStream input,
+ final UnknownFieldSet.Builder unknownFields,
+ final ExtensionRegistryLite extensionRegistry,
+ final int tag) throws IOException {
return unknownFields.mergeFieldFrom(tag, input);
}
-
- /**
- * Adds the {@code values} to the {@code list}.
- *
- * @throws NullPointerException if any of the elements of {@code values} is
- * null.
- */
- protected <T> void addAll(Iterable<T> values, Collection<? super T> list) {
- for (T value : values) {
- if (value == null) {
- throw new NullPointerException();
- }
- }
- if (values instanceof Collection) {
- @SuppressWarnings("unsafe")
- Collection<T> collection = (Collection<T>) values;
- list.addAll(collection);
- } else {
- for (T value : values) {
- list.add(value);
- }
- }
- }
}
// =================================================================
@@ -355,10 +314,10 @@ public abstract class GeneratedMessage extends AbstractMessage {
MessageType extends ExtendableMessage>
extends GeneratedMessage {
protected ExtendableMessage() {}
- private final FieldSet extensions = FieldSet.newFieldSet();
+ private final FieldSet<FieldDescriptor> extensions = FieldSet.newFieldSet();
- private final void verifyExtensionContainingType(
- GeneratedExtension<MessageType, ?> extension) {
+ private void verifyExtensionContainingType(
+ final GeneratedExtension<MessageType, ?> extension) {
if (extension.getDescriptor().getContainingType() !=
getDescriptorForType()) {
// This can only happen if someone uses unchecked operations.
@@ -372,26 +331,33 @@ public abstract class GeneratedMessage extends AbstractMessage {
/** Check if a singular extension is present. */
public final boolean hasExtension(
- GeneratedExtension<MessageType, ?> extension) {
+ final GeneratedExtension<MessageType, ?> extension) {
verifyExtensionContainingType(extension);
return extensions.hasField(extension.getDescriptor());
}
/** Get the number of elements in a repeated extension. */
public final <Type> int getExtensionCount(
- GeneratedExtension<MessageType, List<Type>> extension) {
+ final GeneratedExtension<MessageType, List<Type>> extension) {
verifyExtensionContainingType(extension);
- return extensions.getRepeatedFieldCount(extension.getDescriptor());
+ final FieldDescriptor descriptor = extension.getDescriptor();
+ return extensions.getRepeatedFieldCount(descriptor);
}
/** Get the value of an extension. */
@SuppressWarnings("unchecked")
public final <Type> Type getExtension(
- GeneratedExtension<MessageType, Type> extension) {
+ final GeneratedExtension<MessageType, Type> extension) {
verifyExtensionContainingType(extension);
- Object value = extensions.getField(extension.getDescriptor());
+ FieldDescriptor descriptor = extension.getDescriptor();
+ final Object value = extensions.getField(descriptor);
if (value == null) {
- return (Type) extension.getMessageDefaultInstance();
+ if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ return (Type) extension.getMessageDefaultInstance();
+ } else {
+ return (Type) extension.fromReflectionType(
+ descriptor.getDefaultValue());
+ }
} else {
return (Type) extension.fromReflectionType(value);
}
@@ -400,10 +366,12 @@ public abstract class GeneratedMessage extends AbstractMessage {
/** Get one element of a repeated extension. */
@SuppressWarnings("unchecked")
public final <Type> Type getExtension(
- GeneratedExtension<MessageType, List<Type>> extension, int index) {
+ final GeneratedExtension<MessageType, List<Type>> extension,
+ final int index) {
verifyExtensionContainingType(extension);
+ FieldDescriptor descriptor = extension.getDescriptor();
return (Type) extension.singularFromReflectionType(
- extensions.getRepeatedField(extension.getDescriptor(), index));
+ extensions.getRepeatedField(descriptor, index));
}
/** Called by subclasses to check if all extensions are initialized. */
@@ -411,6 +379,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
return extensions.isInitialized();
}
+ @Override
public boolean isInitialized() {
return super.isInitialized() && extensionsAreInitialized();
}
@@ -425,20 +394,30 @@ public abstract class GeneratedMessage extends AbstractMessage {
// Imagine how much simpler this code would be if Java iterators had
// a way to get the next element without advancing the iterator.
- final Iterator<Map.Entry<FieldDescriptor, Object>> iter =
+ private final Iterator<Map.Entry<FieldDescriptor, Object>> iter =
extensions.iterator();
- Map.Entry<FieldDescriptor, Object> next = null;
+ private Map.Entry<FieldDescriptor, Object> next;
+ private final boolean messageSetWireFormat;
- private ExtensionWriter() {
+ private ExtensionWriter(final boolean messageSetWireFormat) {
if (iter.hasNext()) {
next = iter.next();
}
+ this.messageSetWireFormat = messageSetWireFormat;
}
- public void writeUntil(int end, CodedOutputStream output)
+ public void writeUntil(final int end, final CodedOutputStream output)
throws IOException {
while (next != null && next.getKey().getNumber() < end) {
- extensions.writeField(next.getKey(), next.getValue(), output);
+ FieldDescriptor descriptor = next.getKey();
+ if (messageSetWireFormat && descriptor.getLiteJavaType() ==
+ WireFormat.JavaType.MESSAGE &&
+ !descriptor.isRepeated()) {
+ output.writeMessageSetExtension(descriptor.getNumber(),
+ (Message) next.getValue());
+ } else {
+ FieldSet.writeField(descriptor, next.getValue(), output);
+ }
if (iter.hasNext()) {
next = iter.next();
} else {
@@ -449,24 +428,32 @@ public abstract class GeneratedMessage extends AbstractMessage {
}
protected ExtensionWriter newExtensionWriter() {
- return new ExtensionWriter();
+ return new ExtensionWriter(false);
+ }
+ protected ExtensionWriter newMessageSetExtensionWriter() {
+ return new ExtensionWriter(true);
}
/** Called by subclasses to compute the size of extensions. */
protected int extensionsSerializedSize() {
return extensions.getSerializedSize();
}
+ protected int extensionsSerializedSizeAsMessageSet() {
+ return extensions.getMessageSetSerializedSize();
+ }
// ---------------------------------------------------------------
// Reflection
- public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
- Map<FieldDescriptor, Object> result = super.getAllFieldsMutable();
+ @Override
+ public Map<FieldDescriptor, Object> getAllFields() {
+ final Map<FieldDescriptor, Object> result = super.getAllFieldsMutable();
result.putAll(extensions.getAllFields());
return Collections.unmodifiableMap(result);
}
- public boolean hasField(FieldDescriptor field) {
+ @Override
+ public boolean hasField(final FieldDescriptor field) {
if (field.isExtension()) {
verifyContainingType(field);
return extensions.hasField(field);
@@ -475,14 +462,19 @@ public abstract class GeneratedMessage extends AbstractMessage {
}
}
- public Object getField(FieldDescriptor field) {
+ @Override
+ public Object getField(final FieldDescriptor field) {
if (field.isExtension()) {
verifyContainingType(field);
- Object value = extensions.getField(field);
+ final Object value = extensions.getField(field);
if (value == null) {
- // Lacking an ExtensionRegistry, we have no way to determine the
- // extension's real type, so we return a DynamicMessage.
- return DynamicMessage.getDefaultInstance(field.getMessageType());
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ // Lacking an ExtensionRegistry, we have no way to determine the
+ // extension's real type, so we return a DynamicMessage.
+ return DynamicMessage.getDefaultInstance(field.getMessageType());
+ } else {
+ return field.getDefaultValue();
+ }
} else {
return value;
}
@@ -491,7 +483,8 @@ public abstract class GeneratedMessage extends AbstractMessage {
}
}
- public int getRepeatedFieldCount(FieldDescriptor field) {
+ @Override
+ public int getRepeatedFieldCount(final FieldDescriptor field) {
if (field.isExtension()) {
verifyContainingType(field);
return extensions.getRepeatedFieldCount(field);
@@ -500,7 +493,9 @@ public abstract class GeneratedMessage extends AbstractMessage {
}
}
- public Object getRepeatedField(FieldDescriptor field, int index) {
+ @Override
+ public Object getRepeatedField(final FieldDescriptor field,
+ final int index) {
if (field.isExtension()) {
verifyContainingType(field);
return extensions.getRepeatedField(field, index);
@@ -509,7 +504,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
}
}
- private void verifyContainingType(FieldDescriptor field) {
+ private void verifyContainingType(final FieldDescriptor field) {
if (field.getContainingType() != getDescriptorForType()) {
throw new IllegalArgumentException(
"FieldDescriptor does not match message type.");
@@ -558,70 +553,87 @@ public abstract class GeneratedMessage extends AbstractMessage {
public abstract static class ExtendableBuilder<
MessageType extends ExtendableMessage,
BuilderType extends ExtendableBuilder>
- extends GeneratedMessage.Builder<BuilderType> {
+ extends Builder<BuilderType> {
protected ExtendableBuilder() {}
+
+ // This is implemented here only to work around an apparent bug in the
+ // Java compiler and/or build system. See bug #1898463. The mere presence
+ // of this dummy clone() implementation makes it go away.
+ @Override
+ public BuilderType clone() {
+ throw new UnsupportedOperationException(
+ "This is supposed to be overridden by subclasses.");
+ }
+
+ @Override
protected abstract ExtendableMessage<MessageType> internalGetResult();
/** Check if a singular extension is present. */
public final boolean hasExtension(
- GeneratedExtension<MessageType, ?> extension) {
+ final GeneratedExtension<MessageType, ?> extension) {
return internalGetResult().hasExtension(extension);
}
/** Get the number of elements in a repeated extension. */
public final <Type> int getExtensionCount(
- GeneratedExtension<MessageType, List<Type>> extension) {
+ final GeneratedExtension<MessageType, List<Type>> extension) {
return internalGetResult().getExtensionCount(extension);
}
/** Get the value of an extension. */
public final <Type> Type getExtension(
- GeneratedExtension<MessageType, Type> extension) {
+ final GeneratedExtension<MessageType, Type> extension) {
return internalGetResult().getExtension(extension);
}
/** Get one element of a repeated extension. */
public final <Type> Type getExtension(
- GeneratedExtension<MessageType, List<Type>> extension, int index) {
+ final GeneratedExtension<MessageType, List<Type>> extension,
+ final int index) {
return internalGetResult().getExtension(extension, index);
}
/** Set the value of an extension. */
public final <Type> BuilderType setExtension(
- GeneratedExtension<MessageType, Type> extension, Type value) {
- ExtendableMessage<MessageType> message = internalGetResult();
+ final GeneratedExtension<MessageType, Type> extension,
+ final Type value) {
+ final ExtendableMessage<MessageType> message = internalGetResult();
message.verifyExtensionContainingType(extension);
- message.extensions.setField(extension.getDescriptor(),
+ final FieldDescriptor descriptor = extension.getDescriptor();
+ message.extensions.setField(descriptor,
extension.toReflectionType(value));
return (BuilderType) this;
}
/** Set the value of one element of a repeated extension. */
public final <Type> BuilderType setExtension(
- GeneratedExtension<MessageType, List<Type>> extension,
- int index, Type value) {
- ExtendableMessage<MessageType> message = internalGetResult();
+ final GeneratedExtension<MessageType, List<Type>> extension,
+ final int index, final Type value) {
+ final ExtendableMessage<MessageType> message = internalGetResult();
message.verifyExtensionContainingType(extension);
+ final FieldDescriptor descriptor = extension.getDescriptor();
message.extensions.setRepeatedField(
- extension.getDescriptor(), index,
+ descriptor, index,
extension.singularToReflectionType(value));
return (BuilderType) this;
}
/** Append a value to a repeated extension. */
public final <Type> BuilderType addExtension(
- GeneratedExtension<MessageType, List<Type>> extension, Type value) {
- ExtendableMessage<MessageType> message = internalGetResult();
+ final GeneratedExtension<MessageType, List<Type>> extension,
+ final Type value) {
+ final ExtendableMessage<MessageType> message = internalGetResult();
message.verifyExtensionContainingType(extension);
+ final FieldDescriptor descriptor = extension.getDescriptor();
message.extensions.addRepeatedField(
- extension.getDescriptor(), extension.singularToReflectionType(value));
+ descriptor, extension.singularToReflectionType(value));
return (BuilderType) this;
}
/** Clear an extension. */
public final <Type> BuilderType clearExtension(
- GeneratedExtension<MessageType, ?> extension) {
- ExtendableMessage<MessageType> message = internalGetResult();
+ final GeneratedExtension<MessageType, ?> extension) {
+ final ExtendableMessage<MessageType> message = internalGetResult();
message.verifyExtensionContainingType(extension);
message.extensions.clearField(extension.getDescriptor());
return (BuilderType) this;
@@ -631,13 +643,14 @@ public abstract class GeneratedMessage extends AbstractMessage {
* Called by subclasses to parse an unknown field or an extension.
* @return {@code true} unless the tag is an end-group tag.
*/
- protected boolean parseUnknownField(CodedInputStream input,
- UnknownFieldSet.Builder unknownFields,
- ExtensionRegistry extensionRegistry,
- int tag)
- throws IOException {
- ExtendableMessage<MessageType> message = internalGetResult();
- return message.extensions.mergeFieldFrom(
+ @Override
+ protected boolean parseUnknownField(
+ final CodedInputStream input,
+ final UnknownFieldSet.Builder unknownFields,
+ final ExtensionRegistryLite extensionRegistry,
+ final int tag) throws IOException {
+ final ExtendableMessage<MessageType> message = internalGetResult();
+ return AbstractMessage.Builder.mergeFieldFrom(
input, unknownFields, extensionRegistry, this, tag);
}
@@ -647,9 +660,11 @@ public abstract class GeneratedMessage extends AbstractMessage {
// We don't have to override the get*() methods here because they already
// just forward to the underlying message.
- public BuilderType setField(FieldDescriptor field, Object value) {
+ @Override
+ public BuilderType setField(final FieldDescriptor field,
+ final Object value) {
if (field.isExtension()) {
- ExtendableMessage<MessageType> message = internalGetResult();
+ final ExtendableMessage<MessageType> message = internalGetResult();
message.verifyContainingType(field);
message.extensions.setField(field, value);
return (BuilderType) this;
@@ -658,9 +673,10 @@ public abstract class GeneratedMessage extends AbstractMessage {
}
}
- public BuilderType clearField(Descriptors.FieldDescriptor field) {
+ @Override
+ public BuilderType clearField(final FieldDescriptor field) {
if (field.isExtension()) {
- ExtendableMessage<MessageType> message = internalGetResult();
+ final ExtendableMessage<MessageType> message = internalGetResult();
message.verifyContainingType(field);
message.extensions.clearField(field);
return (BuilderType) this;
@@ -669,10 +685,11 @@ public abstract class GeneratedMessage extends AbstractMessage {
}
}
- public BuilderType setRepeatedField(Descriptors.FieldDescriptor field,
- int index, Object value) {
+ @Override
+ public BuilderType setRepeatedField(final FieldDescriptor field,
+ final int index, final Object value) {
if (field.isExtension()) {
- ExtendableMessage<MessageType> message = internalGetResult();
+ final ExtendableMessage<MessageType> message = internalGetResult();
message.verifyContainingType(field);
message.extensions.setRepeatedField(field, index, value);
return (BuilderType) this;
@@ -681,10 +698,11 @@ public abstract class GeneratedMessage extends AbstractMessage {
}
}
- public BuilderType addRepeatedField(Descriptors.FieldDescriptor field,
- Object value) {
+ @Override
+ public BuilderType addRepeatedField(final FieldDescriptor field,
+ final Object value) {
if (field.isExtension()) {
- ExtendableMessage<MessageType> message = internalGetResult();
+ final ExtendableMessage<MessageType> message = internalGetResult();
message.verifyContainingType(field);
message.extensions.addRepeatedField(field, value);
return (BuilderType) this;
@@ -693,7 +711,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
}
}
- protected final void mergeExtensionFields(ExtendableMessage other) {
+ protected final void mergeExtensionFields(final ExtendableMessage other) {
internalGetResult().extensions.mergeFrom(other.extensions);
}
}
@@ -703,7 +721,8 @@ public abstract class GeneratedMessage extends AbstractMessage {
/** For use by generated code only. */
public static <ContainingType extends Message, Type>
GeneratedExtension<ContainingType, Type>
- newGeneratedExtension(FieldDescriptor descriptor, Class<Type> type) {
+ newGeneratedExtension(final FieldDescriptor descriptor,
+ final Class<Type> type) {
if (descriptor.isRepeated()) {
throw new IllegalArgumentException(
"Must call newRepeatedGeneratedExtension() for repeated types.");
@@ -715,7 +734,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
public static <ContainingType extends Message, Type>
GeneratedExtension<ContainingType, List<Type>>
newRepeatedGeneratedExtension(
- FieldDescriptor descriptor, Class<Type> type) {
+ final FieldDescriptor descriptor, final Class<Type> type) {
if (!descriptor.isRepeated()) {
throw new IllegalArgumentException(
"Must call newGeneratedExtension() for non-repeated types.");
@@ -753,7 +772,8 @@ public abstract class GeneratedMessage extends AbstractMessage {
// TODO(kenton): Find ways to avoid using Java reflection within this
// class. Also try to avoid suppressing unchecked warnings.
- private GeneratedExtension(FieldDescriptor descriptor, Class type) {
+ private GeneratedExtension(final FieldDescriptor descriptor,
+ final Class type) {
if (!descriptor.isExtension()) {
throw new IllegalArgumentException(
"GeneratedExtension given a regular (non-extension) field.");
@@ -808,13 +828,13 @@ public abstract class GeneratedMessage extends AbstractMessage {
* type.
*/
@SuppressWarnings("unchecked")
- private Object fromReflectionType(Object value) {
+ private Object fromReflectionType(final Object value) {
if (descriptor.isRepeated()) {
if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE ||
descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) {
// Must convert the whole list.
- List result = new ArrayList();
- for (Object element : (List) value) {
+ final List result = new ArrayList();
+ for (final Object element : (List) value) {
result.add(singularFromReflectionType(element));
}
return result;
@@ -830,7 +850,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
* Like {@link #fromReflectionType(Object)}, but if the type is a repeated
* type, this converts a single element.
*/
- private Object singularFromReflectionType(Object value) {
+ private Object singularFromReflectionType(final Object value) {
switch (descriptor.getJavaType()) {
case MESSAGE:
if (type.isInstance(value)) {
@@ -859,12 +879,12 @@ public abstract class GeneratedMessage extends AbstractMessage {
* type.
*/
@SuppressWarnings("unchecked")
- private Object toReflectionType(Object value) {
+ private Object toReflectionType(final Object value) {
if (descriptor.isRepeated()) {
if (descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) {
// Must convert the whole list.
- List result = new ArrayList();
- for (Object element : (List) value) {
+ final List result = new ArrayList();
+ for (final Object element : (List) value) {
result.add(singularToReflectionType(element));
}
return result;
@@ -880,7 +900,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
* Like {@link #toReflectionType(Object)}, but if the type is a repeated
* type, this converts a single element.
*/
- private Object singularToReflectionType(Object value) {
+ private Object singularToReflectionType(final Object value) {
switch (descriptor.getJavaType()) {
case ENUM:
return invokeOrDie(enumGetValueDescriptor, value);
@@ -895,7 +915,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
/** Calls Class.getMethod and throws a RuntimeException if it fails. */
@SuppressWarnings("unchecked")
private static Method getMethodOrDie(
- Class clazz, String name, Class... params) {
+ final Class clazz, final String name, final Class... params) {
try {
return clazz.getMethod(name, params);
} catch (NoSuchMethodException e) {
@@ -907,15 +927,15 @@ public abstract class GeneratedMessage extends AbstractMessage {
/** Calls invoke and throws a RuntimeException if it fails. */
private static Object invokeOrDie(
- Method method, Object object, Object... params) {
+ final Method method, final Object object, final Object... params) {
try {
return method.invoke(object, params);
} catch (IllegalAccessException e) {
throw new RuntimeException(
"Couldn't use Java reflection to implement protocol message " +
"reflection.", e);
- } catch (java.lang.reflect.InvocationTargetException e) {
- Throwable cause = e.getCause();
+ } catch (InvocationTargetException e) {
+ final Throwable cause = e.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
@@ -944,15 +964,15 @@ public abstract class GeneratedMessage extends AbstractMessage {
* @param builderClass The builder type.
*/
public FieldAccessorTable(
- Descriptor descriptor,
- String[] camelCaseNames,
- Class<? extends GeneratedMessage> messageClass,
- Class<? extends GeneratedMessage.Builder> builderClass) {
+ final Descriptor descriptor,
+ final String[] camelCaseNames,
+ final Class<? extends GeneratedMessage> messageClass,
+ final Class<? extends Builder> builderClass) {
this.descriptor = descriptor;
fields = new FieldAccessor[descriptor.getFields().size()];
for (int i = 0; i < fields.length; i++) {
- FieldDescriptor field = descriptor.getFields().get(i);
+ final FieldDescriptor field = descriptor.getFields().get(i);
if (field.isRepeated()) {
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
fields[i] = new RepeatedMessageFieldAccessor(
@@ -983,7 +1003,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
private final FieldAccessor[] fields;
/** Get the FieldAccessor for a particular field. */
- private FieldAccessor getField(FieldDescriptor field) {
+ private FieldAccessor getField(final FieldDescriptor field) {
if (field.getContainingType() != descriptor) {
throw new IllegalArgumentException(
"FieldDescriptor does not match message type.");
@@ -1000,16 +1020,16 @@ public abstract class GeneratedMessage extends AbstractMessage {
* Abstract interface that provides access to a single field. This is
* implemented differently depending on the field type and cardinality.
*/
- private static interface FieldAccessor {
+ private interface FieldAccessor {
Object get(GeneratedMessage message);
- void set(GeneratedMessage.Builder builder, Object value);
+ void set(Builder builder, Object value);
Object getRepeated(GeneratedMessage message, int index);
- void setRepeated(GeneratedMessage.Builder builder,
+ void setRepeated(Builder builder,
int index, Object value);
- void addRepeated(GeneratedMessage.Builder builder, Object value);
+ void addRepeated(Builder builder, Object value);
boolean has(GeneratedMessage message);
int getRepeatedCount(GeneratedMessage message);
- void clear(GeneratedMessage.Builder builder);
+ void clear(Builder builder);
Message.Builder newBuilder();
}
@@ -1017,9 +1037,9 @@ public abstract class GeneratedMessage extends AbstractMessage {
private static class SingularFieldAccessor implements FieldAccessor {
SingularFieldAccessor(
- FieldDescriptor descriptor, String camelCaseName,
- Class<? extends GeneratedMessage> messageClass,
- Class<? extends GeneratedMessage.Builder> builderClass) {
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessage> messageClass,
+ final Class<? extends Builder> builderClass) {
getMethod = getMethodOrDie(messageClass, "get" + camelCaseName);
type = getMethod.getReturnType();
setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, type);
@@ -1031,39 +1051,40 @@ public abstract class GeneratedMessage extends AbstractMessage {
// Note: We use Java reflection to call public methods rather than
// access private fields directly as this avoids runtime security
// checks.
- Class type;
- Method getMethod;
- Method setMethod;
- Method hasMethod;
- Method clearMethod;
+ protected final Class type;
+ protected final Method getMethod;
+ protected final Method setMethod;
+ protected final Method hasMethod;
+ protected final Method clearMethod;
- public Object get(GeneratedMessage message) {
+ public Object get(final GeneratedMessage message) {
return invokeOrDie(getMethod, message);
}
- public void set(GeneratedMessage.Builder builder, Object value) {
+ public void set(final Builder builder, final Object value) {
invokeOrDie(setMethod, builder, value);
}
- public Object getRepeated(GeneratedMessage message, int index) {
+ public Object getRepeated(final GeneratedMessage message,
+ final int index) {
throw new UnsupportedOperationException(
"getRepeatedField() called on a singular field.");
}
- public void setRepeated(GeneratedMessage.Builder builder,
- int index, Object value) {
+ public void setRepeated(final Builder builder,
+ final int index, final Object value) {
throw new UnsupportedOperationException(
"setRepeatedField() called on a singular field.");
}
- public void addRepeated(GeneratedMessage.Builder builder, Object value) {
+ public void addRepeated(final Builder builder, final Object value) {
throw new UnsupportedOperationException(
"addRepeatedField() called on a singular field.");
}
- public boolean has(GeneratedMessage message) {
+ public boolean has(final GeneratedMessage message) {
return (Boolean) invokeOrDie(hasMethod, message);
}
- public int getRepeatedCount(GeneratedMessage message) {
+ public int getRepeatedCount(final GeneratedMessage message) {
throw new UnsupportedOperationException(
"getRepeatedFieldSize() called on a singular field.");
}
- public void clear(GeneratedMessage.Builder builder) {
+ public void clear(final Builder builder) {
invokeOrDie(clearMethod, builder);
}
public Message.Builder newBuilder() {
@@ -1074,10 +1095,11 @@ public abstract class GeneratedMessage extends AbstractMessage {
private static class RepeatedFieldAccessor implements FieldAccessor {
RepeatedFieldAccessor(
- FieldDescriptor descriptor, String camelCaseName,
- Class<? extends GeneratedMessage> messageClass,
- Class<? extends GeneratedMessage.Builder> builderClass) {
- getMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "List");
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessage> messageClass,
+ final Class<? extends Builder> builderClass) {
+ getMethod = getMethodOrDie(messageClass,
+ "get" + camelCaseName + "List");
getRepeatedMethod =
getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE);
@@ -1093,45 +1115,46 @@ public abstract class GeneratedMessage extends AbstractMessage {
clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
}
- Class type;
- Method getMethod;
- Method getRepeatedMethod;
- Method setRepeatedMethod;
- Method addRepeatedMethod;
- Method getCountMethod;
- Method clearMethod;
+ protected final Class type;
+ protected final Method getMethod;
+ protected final Method getRepeatedMethod;
+ protected final Method setRepeatedMethod;
+ protected final Method addRepeatedMethod;
+ protected final Method getCountMethod;
+ protected final Method clearMethod;
- public Object get(GeneratedMessage message) {
+ public Object get(final GeneratedMessage message) {
return invokeOrDie(getMethod, message);
}
- public void set(GeneratedMessage.Builder builder, Object value) {
+ public void set(final Builder builder, final Object value) {
// Add all the elements individually. This serves two purposes:
// 1) Verifies that each element has the correct type.
// 2) Insures that the caller cannot modify the list later on and
// have the modifications be reflected in the message.
clear(builder);
- for (Object element : (List) value) {
+ for (final Object element : (List) value) {
addRepeated(builder, element);
}
}
- public Object getRepeated(GeneratedMessage message, int index) {
+ public Object getRepeated(final GeneratedMessage message,
+ final int index) {
return invokeOrDie(getRepeatedMethod, message, index);
}
- public void setRepeated(GeneratedMessage.Builder builder,
- int index, Object value) {
+ public void setRepeated(final Builder builder,
+ final int index, final Object value) {
invokeOrDie(setRepeatedMethod, builder, index, value);
}
- public void addRepeated(GeneratedMessage.Builder builder, Object value) {
+ public void addRepeated(final Builder builder, final Object value) {
invokeOrDie(addRepeatedMethod, builder, value);
}
- public boolean has(GeneratedMessage message) {
+ public boolean has(final GeneratedMessage message) {
throw new UnsupportedOperationException(
"hasField() called on a singular field.");
}
- public int getRepeatedCount(GeneratedMessage message) {
+ public int getRepeatedCount(final GeneratedMessage message) {
return (Integer) invokeOrDie(getCountMethod, message);
}
- public void clear(GeneratedMessage.Builder builder) {
+ public void clear(final Builder builder) {
invokeOrDie(clearMethod, builder);
}
public Message.Builder newBuilder() {
@@ -1145,9 +1168,9 @@ public abstract class GeneratedMessage extends AbstractMessage {
private static final class SingularEnumFieldAccessor
extends SingularFieldAccessor {
SingularEnumFieldAccessor(
- FieldDescriptor descriptor, String camelCaseName,
- Class<? extends GeneratedMessage> messageClass,
- Class<? extends GeneratedMessage.Builder> builderClass) {
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessage> messageClass,
+ final Class<? extends Builder> builderClass) {
super(descriptor, camelCaseName, messageClass, builderClass);
valueOfMethod = getMethodOrDie(type, "valueOf",
@@ -1159,10 +1182,12 @@ public abstract class GeneratedMessage extends AbstractMessage {
private Method valueOfMethod;
private Method getValueDescriptorMethod;
- public Object get(GeneratedMessage message) {
+ @Override
+ public Object get(final GeneratedMessage message) {
return invokeOrDie(getValueDescriptorMethod, super.get(message));
}
- public void set(GeneratedMessage.Builder builder, Object value) {
+ @Override
+ public void set(final Builder builder, final Object value) {
super.set(builder, invokeOrDie(valueOfMethod, null, value));
}
}
@@ -1170,9 +1195,9 @@ public abstract class GeneratedMessage extends AbstractMessage {
private static final class RepeatedEnumFieldAccessor
extends RepeatedFieldAccessor {
RepeatedEnumFieldAccessor(
- FieldDescriptor descriptor, String camelCaseName,
- Class<? extends GeneratedMessage> messageClass,
- Class<? extends GeneratedMessage.Builder> builderClass) {
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessage> messageClass,
+ final Class<? extends Builder> builderClass) {
super(descriptor, camelCaseName, messageClass, builderClass);
valueOfMethod = getMethodOrDie(type, "valueOf",
@@ -1181,26 +1206,32 @@ public abstract class GeneratedMessage extends AbstractMessage {
getMethodOrDie(type, "getValueDescriptor");
}
- private Method valueOfMethod;
- private Method getValueDescriptorMethod;
+ private final Method valueOfMethod;
+ private final Method getValueDescriptorMethod;
+ @Override
@SuppressWarnings("unchecked")
- public Object get(GeneratedMessage message) {
- List newList = new ArrayList();
- for (Object element : (List) super.get(message)) {
+ public Object get(final GeneratedMessage message) {
+ final List newList = new ArrayList();
+ for (final Object element : (List) super.get(message)) {
newList.add(invokeOrDie(getValueDescriptorMethod, element));
}
return Collections.unmodifiableList(newList);
}
- public Object getRepeated(GeneratedMessage message, int index) {
+ @Override
+ public Object getRepeated(final GeneratedMessage message,
+ final int index) {
return invokeOrDie(getValueDescriptorMethod,
super.getRepeated(message, index));
}
- public void setRepeated(GeneratedMessage.Builder builder,
- int index, Object value) {
- super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null, value));
+ @Override
+ public void setRepeated(final Builder builder,
+ final int index, final Object value) {
+ super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null,
+ value));
}
- public void addRepeated(GeneratedMessage.Builder builder, Object value) {
+ @Override
+ public void addRepeated(final Builder builder, final Object value) {
super.addRepeated(builder, invokeOrDie(valueOfMethod, null, value));
}
}
@@ -1210,17 +1241,17 @@ public abstract class GeneratedMessage extends AbstractMessage {
private static final class SingularMessageFieldAccessor
extends SingularFieldAccessor {
SingularMessageFieldAccessor(
- FieldDescriptor descriptor, String camelCaseName,
- Class<? extends GeneratedMessage> messageClass,
- Class<? extends GeneratedMessage.Builder> builderClass) {
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessage> messageClass,
+ final Class<? extends Builder> builderClass) {
super(descriptor, camelCaseName, messageClass, builderClass);
newBuilderMethod = getMethodOrDie(type, "newBuilder");
}
- private Method newBuilderMethod;
+ private final Method newBuilderMethod;
- private Object coerceType(Object value) {
+ private Object coerceType(final Object value) {
if (type.isInstance(value)) {
return value;
} else {
@@ -1233,9 +1264,11 @@ public abstract class GeneratedMessage extends AbstractMessage {
}
}
- public void set(GeneratedMessage.Builder builder, Object value) {
+ @Override
+ public void set(final Builder builder, final Object value) {
super.set(builder, coerceType(value));
}
+ @Override
public Message.Builder newBuilder() {
return (Message.Builder) invokeOrDie(newBuilderMethod, null);
}
@@ -1244,17 +1277,17 @@ public abstract class GeneratedMessage extends AbstractMessage {
private static final class RepeatedMessageFieldAccessor
extends RepeatedFieldAccessor {
RepeatedMessageFieldAccessor(
- FieldDescriptor descriptor, String camelCaseName,
- Class<? extends GeneratedMessage> messageClass,
- Class<? extends GeneratedMessage.Builder> builderClass) {
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessage> messageClass,
+ final Class<? extends Builder> builderClass) {
super(descriptor, camelCaseName, messageClass, builderClass);
newBuilderMethod = getMethodOrDie(type, "newBuilder");
}
- private Method newBuilderMethod;
+ private final Method newBuilderMethod;
- private Object coerceType(Object value) {
+ private Object coerceType(final Object value) {
if (type.isInstance(value)) {
return value;
} else {
@@ -1267,13 +1300,16 @@ public abstract class GeneratedMessage extends AbstractMessage {
}
}
- public void setRepeated(GeneratedMessage.Builder builder,
- int index, Object value) {
+ @Override
+ public void setRepeated(final Builder builder,
+ final int index, final Object value) {
super.setRepeated(builder, index, coerceType(value));
}
- public void addRepeated(GeneratedMessage.Builder builder, Object value) {
+ @Override
+ public void addRepeated(final Builder builder, final Object value) {
super.addRepeated(builder, coerceType(value));
}
+ @Override
public Message.Builder newBuilder() {
return (Message.Builder) invokeOrDie(newBuilderMethod, null);
}
diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
new file mode 100644
index 00000000..c68414bd
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -0,0 +1,539 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Lite version of {@link GeneratedMessage}.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public abstract class GeneratedMessageLite extends AbstractMessageLite {
+ protected GeneratedMessageLite() {}
+
+ @SuppressWarnings("unchecked")
+ public abstract static class Builder<MessageType extends GeneratedMessageLite,
+ BuilderType extends Builder>
+ extends AbstractMessageLite.Builder<BuilderType> {
+ protected Builder() {}
+
+ // This is implemented here only to work around an apparent bug in the
+ // Java compiler and/or build system. See bug #1898463. The mere presence
+ // of this dummy clone() implementation makes it go away.
+ @Override
+ public BuilderType clone() {
+ throw new UnsupportedOperationException(
+ "This is supposed to be overridden by subclasses.");
+ }
+
+ /** All subclasses implement this. */
+ public abstract BuilderType mergeFrom(MessageType message);
+
+ // Defined here for return type covariance.
+ public abstract MessageType getDefaultInstanceForType();
+
+ /**
+ * Get the message being built. We don't just pass this to the
+ * constructor because it becomes null when build() is called.
+ */
+ protected abstract MessageType internalGetResult();
+
+ /**
+ * Called by subclasses to parse an unknown field.
+ * @return {@code true} unless the tag is an end-group tag.
+ */
+ protected boolean parseUnknownField(
+ final CodedInputStream input,
+ final ExtensionRegistryLite extensionRegistry,
+ final int tag) throws IOException {
+ return input.skipField(tag);
+ }
+ }
+
+ // =================================================================
+ // Extensions-related stuff
+
+ /**
+ * Lite equivalent of {@link GeneratedMessage.ExtendableMessage}.
+ */
+ public abstract static class ExtendableMessage<
+ MessageType extends ExtendableMessage<MessageType>>
+ extends GeneratedMessageLite {
+ protected ExtendableMessage() {}
+ private final FieldSet<ExtensionDescriptor> extensions =
+ FieldSet.newFieldSet();
+
+ private void verifyExtensionContainingType(
+ final GeneratedExtension<MessageType, ?> extension) {
+ if (extension.getContainingTypeDefaultInstance() !=
+ getDefaultInstanceForType()) {
+ // This can only happen if someone uses unchecked operations.
+ throw new IllegalArgumentException(
+ "This extension is for a different message type. Please make " +
+ "sure that you are not suppressing any generics type warnings.");
+ }
+ }
+
+ /** Check if a singular extension is present. */
+ public final boolean hasExtension(
+ final GeneratedExtension<MessageType, ?> extension) {
+ verifyExtensionContainingType(extension);
+ return extensions.hasField(extension.descriptor);
+ }
+
+ /** Get the number of elements in a repeated extension. */
+ public final <Type> int getExtensionCount(
+ final GeneratedExtension<MessageType, List<Type>> extension) {
+ verifyExtensionContainingType(extension);
+ return extensions.getRepeatedFieldCount(extension.descriptor);
+ }
+
+ /** Get the value of an extension. */
+ @SuppressWarnings("unchecked")
+ public final <Type> Type getExtension(
+ final GeneratedExtension<MessageType, Type> extension) {
+ verifyExtensionContainingType(extension);
+ final Object value = extensions.getField(extension.descriptor);
+ if (value == null) {
+ return extension.defaultValue;
+ } else {
+ return (Type) value;
+ }
+ }
+
+ /** Get one element of a repeated extension. */
+ @SuppressWarnings("unchecked")
+ public final <Type> Type getExtension(
+ final GeneratedExtension<MessageType, List<Type>> extension,
+ final int index) {
+ verifyExtensionContainingType(extension);
+ return (Type) extensions.getRepeatedField(extension.descriptor, index);
+ }
+
+ /** Called by subclasses to check if all extensions are initialized. */
+ protected boolean extensionsAreInitialized() {
+ return extensions.isInitialized();
+ }
+
+ /**
+ * Used by subclasses to serialize extensions. Extension ranges may be
+ * interleaved with field numbers, but we must write them in canonical
+ * (sorted by field number) order. ExtensionWriter helps us write
+ * individual ranges of extensions at once.
+ */
+ protected class ExtensionWriter {
+ // Imagine how much simpler this code would be if Java iterators had
+ // a way to get the next element without advancing the iterator.
+
+ private final Iterator<Map.Entry<ExtensionDescriptor, Object>> iter =
+ extensions.iterator();
+ private Map.Entry<ExtensionDescriptor, Object> next;
+ private final boolean messageSetWireFormat;
+
+ private ExtensionWriter(boolean messageSetWireFormat) {
+ if (iter.hasNext()) {
+ next = iter.next();
+ }
+ this.messageSetWireFormat = messageSetWireFormat;
+ }
+
+ public void writeUntil(final int end, final CodedOutputStream output)
+ throws IOException {
+ while (next != null && next.getKey().getNumber() < end) {
+ ExtensionDescriptor extension = next.getKey();
+ if (messageSetWireFormat && extension.getLiteJavaType() ==
+ WireFormat.JavaType.MESSAGE &&
+ !extension.isRepeated()) {
+ output.writeMessageSetExtension(extension.getNumber(),
+ (MessageLite) next.getValue());
+ } else {
+ FieldSet.writeField(extension, next.getValue(), output);
+ }
+ if (iter.hasNext()) {
+ next = iter.next();
+ } else {
+ next = null;
+ }
+ }
+ }
+ }
+
+ protected ExtensionWriter newExtensionWriter() {
+ return new ExtensionWriter(false);
+ }
+ protected ExtensionWriter newMessageSetExtensionWriter() {
+ return new ExtensionWriter(true);
+ }
+
+ /** Called by subclasses to compute the size of extensions. */
+ protected int extensionsSerializedSize() {
+ return extensions.getSerializedSize();
+ }
+ protected int extensionsSerializedSizeAsMessageSet() {
+ return extensions.getMessageSetSerializedSize();
+ }
+ }
+
+ /**
+ * Lite equivalent of {@link GeneratedMessage.ExtendableBuilder}.
+ */
+ @SuppressWarnings("unchecked")
+ public abstract static class ExtendableBuilder<
+ MessageType extends ExtendableMessage<MessageType>,
+ BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
+ extends Builder<MessageType, BuilderType> {
+ protected ExtendableBuilder() {}
+
+ // This is implemented here only to work around an apparent bug in the
+ // Java compiler and/or build system. See bug #1898463. The mere presence
+ // of this dummy clone() implementation makes it go away.
+ @Override
+ public BuilderType clone() {
+ throw new UnsupportedOperationException(
+ "This is supposed to be overridden by subclasses.");
+ }
+
+ @Override
+ protected abstract MessageType internalGetResult();
+
+ /** Check if a singular extension is present. */
+ public final boolean hasExtension(
+ final GeneratedExtension<MessageType, ?> extension) {
+ return internalGetResult().hasExtension(extension);
+ }
+
+ /** Get the number of elements in a repeated extension. */
+ public final <Type> int getExtensionCount(
+ final GeneratedExtension<MessageType, List<Type>> extension) {
+ return internalGetResult().getExtensionCount(extension);
+ }
+
+ /** Get the value of an extension. */
+ public final <Type> Type getExtension(
+ final GeneratedExtension<MessageType, Type> extension) {
+ return internalGetResult().getExtension(extension);
+ }
+
+ /** Get one element of a repeated extension. */
+ public final <Type> Type getExtension(
+ final GeneratedExtension<MessageType, List<Type>> extension,
+ final int index) {
+ return internalGetResult().getExtension(extension, index);
+ }
+
+ /** Set the value of an extension. */
+ public final <Type> BuilderType setExtension(
+ final GeneratedExtension<MessageType, Type> extension,
+ final Type value) {
+ final ExtendableMessage<MessageType> message = internalGetResult();
+ message.verifyExtensionContainingType(extension);
+ message.extensions.setField(extension.descriptor, value);
+ return (BuilderType) this;
+ }
+
+ /** Set the value of one element of a repeated extension. */
+ public final <Type> BuilderType setExtension(
+ final GeneratedExtension<MessageType, List<Type>> extension,
+ final int index, final Type value) {
+ final ExtendableMessage<MessageType> message = internalGetResult();
+ message.verifyExtensionContainingType(extension);
+ message.extensions.setRepeatedField(extension.descriptor, index, value);
+ return (BuilderType) this;
+ }
+
+ /** Append a value to a repeated extension. */
+ public final <Type> BuilderType addExtension(
+ final GeneratedExtension<MessageType, List<Type>> extension,
+ final Type value) {
+ final ExtendableMessage<MessageType> message = internalGetResult();
+ message.verifyExtensionContainingType(extension);
+ message.extensions.addRepeatedField(extension.descriptor, value);
+ return (BuilderType) this;
+ }
+
+ /** Clear an extension. */
+ public final <Type> BuilderType clearExtension(
+ final GeneratedExtension<MessageType, ?> extension) {
+ final ExtendableMessage<MessageType> message = internalGetResult();
+ message.verifyExtensionContainingType(extension);
+ message.extensions.clearField(extension.descriptor);
+ return (BuilderType) this;
+ }
+
+ /**
+ * Called by subclasses to parse an unknown field or an extension.
+ * @return {@code true} unless the tag is an end-group tag.
+ */
+ @Override
+ protected boolean parseUnknownField(
+ final CodedInputStream input,
+ final ExtensionRegistryLite extensionRegistry,
+ final int tag) throws IOException {
+ final FieldSet<ExtensionDescriptor> extensions =
+ internalGetResult().extensions;
+
+ final int wireType = WireFormat.getTagWireType(tag);
+ final int fieldNumber = WireFormat.getTagFieldNumber(tag);
+
+ final GeneratedExtension<MessageType, ?> extension =
+ extensionRegistry.findLiteExtensionByNumber(
+ getDefaultInstanceForType(), fieldNumber);
+
+ if (extension == null || wireType !=
+ FieldSet.getWireFormatForFieldType(
+ extension.descriptor.getLiteType(),
+ extension.descriptor.isPacked())) {
+ // Unknown field or wrong wire type. Skip.
+ return input.skipField(tag);
+ }
+
+ if (extension.descriptor.isPacked()) {
+ final int length = input.readRawVarint32();
+ final int limit = input.pushLimit(length);
+ if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) {
+ while (input.getBytesUntilLimit() > 0) {
+ final int rawValue = input.readEnum();
+ final Object value =
+ extension.descriptor.getEnumType().findValueByNumber(rawValue);
+ if (value == null) {
+ // If the number isn't recognized as a valid value for this
+ // enum, drop it (don't even add it to unknownFields).
+ return true;
+ }
+ extensions.addRepeatedField(extension.descriptor, value);
+ }
+ } else {
+ while (input.getBytesUntilLimit() > 0) {
+ final Object value =
+ FieldSet.readPrimitiveField(input,
+ extension.descriptor.getLiteType());
+ extensions.addRepeatedField(extension.descriptor, value);
+ }
+ }
+ input.popLimit(limit);
+ } else {
+ final Object value;
+ switch (extension.descriptor.getLiteJavaType()) {
+ case MESSAGE: {
+ MessageLite.Builder subBuilder = null;
+ if (!extension.descriptor.isRepeated()) {
+ MessageLite existingValue =
+ (MessageLite) extensions.getField(extension.descriptor);
+ if (existingValue != null) {
+ subBuilder = existingValue.toBuilder();
+ }
+ }
+ if (subBuilder == null) {
+ subBuilder = extension.messageDefaultInstance.newBuilderForType();
+ }
+ if (extension.descriptor.getLiteType() ==
+ WireFormat.FieldType.GROUP) {
+ input.readGroup(extension.getNumber(),
+ subBuilder, extensionRegistry);
+ } else {
+ input.readMessage(subBuilder, extensionRegistry);
+ }
+ value = subBuilder.build();
+ break;
+ }
+ case ENUM:
+ final int rawValue = input.readEnum();
+ value = extension.descriptor.getEnumType()
+ .findValueByNumber(rawValue);
+ // If the number isn't recognized as a valid value for this enum,
+ // drop it.
+ if (value == null) {
+ return true;
+ }
+ break;
+ default:
+ value = FieldSet.readPrimitiveField(input,
+ extension.descriptor.getLiteType());
+ break;
+ }
+
+ if (extension.descriptor.isRepeated()) {
+ extensions.addRepeatedField(extension.descriptor, value);
+ } else {
+ extensions.setField(extension.descriptor, value);
+ }
+ }
+
+ return true;
+ }
+
+ protected final void mergeExtensionFields(final MessageType other) {
+ internalGetResult().extensions.mergeFrom(other.extensions);
+ }
+ }
+
+ // -----------------------------------------------------------------
+
+ /** For use by generated code only. */
+ public static <ContainingType extends MessageLite, Type>
+ GeneratedExtension<ContainingType, Type>
+ newGeneratedExtension(
+ final ContainingType containingTypeDefaultInstance,
+ final Type defaultValue,
+ final MessageLite messageDefaultInstance,
+ final Internal.EnumLiteMap<?> enumTypeMap,
+ final int number,
+ final WireFormat.FieldType type) {
+ return new GeneratedExtension<ContainingType, Type>(
+ containingTypeDefaultInstance, defaultValue, messageDefaultInstance,
+ new ExtensionDescriptor(enumTypeMap, number, type,
+ false /* isRepeated */, false /* isPacked */));
+ }
+
+ /** For use by generated code only. */
+ public static <ContainingType extends MessageLite, Type>
+ GeneratedExtension<ContainingType, List<Type>>
+ newRepeatedGeneratedExtension(
+ final ContainingType containingTypeDefaultInstance,
+ final MessageLite messageDefaultInstance,
+ final Internal.EnumLiteMap<?> enumTypeMap,
+ final int number,
+ final WireFormat.FieldType type,
+ final boolean isPacked) {
+ return new GeneratedExtension<ContainingType, List<Type>>(
+ containingTypeDefaultInstance, Collections.<Type>emptyList(),
+ messageDefaultInstance,
+ new ExtensionDescriptor(
+ enumTypeMap, number, type, true /* isRepeated */, isPacked));
+ }
+
+ private static final class ExtensionDescriptor
+ implements FieldSet.FieldDescriptorLite<
+ ExtensionDescriptor> {
+ private ExtensionDescriptor(
+ final Internal.EnumLiteMap<?> enumTypeMap,
+ final int number,
+ final WireFormat.FieldType type,
+ final boolean isRepeated,
+ final boolean isPacked) {
+ this.enumTypeMap = enumTypeMap;
+ this.number = number;
+ this.type = type;
+ this.isRepeated = isRepeated;
+ this.isPacked = isPacked;
+ }
+
+ private final Internal.EnumLiteMap<?> enumTypeMap;
+ private final int number;
+ private final WireFormat.FieldType type;
+ private final boolean isRepeated;
+ private final boolean isPacked;
+
+ public int getNumber() {
+ return number;
+ }
+
+ public WireFormat.FieldType getLiteType() {
+ return type;
+ }
+
+ public WireFormat.JavaType getLiteJavaType() {
+ return type.getJavaType();
+ }
+
+ public boolean isRepeated() {
+ return isRepeated;
+ }
+
+ public boolean isPacked() {
+ return isPacked;
+ }
+
+ public Internal.EnumLiteMap<?> getEnumType() {
+ return enumTypeMap;
+ }
+
+ @SuppressWarnings("unchecked")
+ public MessageLite.Builder internalMergeFrom(
+ MessageLite.Builder to, MessageLite from) {
+ return ((Builder) to).mergeFrom((GeneratedMessageLite) from);
+ }
+
+ public int compareTo(ExtensionDescriptor other) {
+ return number - other.number;
+ }
+ }
+
+ /**
+ * Lite equivalent to {@link GeneratedMessage.GeneratedExtension}.
+ *
+ * Users should ignore the contents of this class and only use objects of
+ * this type as parameters to extension accessors and ExtensionRegistry.add().
+ */
+ public static final class GeneratedExtension<
+ ContainingType extends MessageLite, Type> {
+ private GeneratedExtension(
+ final ContainingType containingTypeDefaultInstance,
+ final Type defaultValue,
+ final MessageLite messageDefaultInstance,
+ final ExtensionDescriptor descriptor) {
+ this.containingTypeDefaultInstance = containingTypeDefaultInstance;
+ this.defaultValue = defaultValue;
+ this.messageDefaultInstance = messageDefaultInstance;
+ this.descriptor = descriptor;
+ }
+
+ private final ContainingType containingTypeDefaultInstance;
+ private final Type defaultValue;
+ private final MessageLite messageDefaultInstance;
+ private final ExtensionDescriptor descriptor;
+
+ /**
+ * Default instance of the type being extended, used to identify that type.
+ */
+ public ContainingType getContainingTypeDefaultInstance() {
+ return containingTypeDefaultInstance;
+ }
+
+ /** Get the field number. */
+ public int getNumber() {
+ return descriptor.getNumber();
+ }
+
+ /**
+ * If the extension is an embedded message, this is the default instance of
+ * that type.
+ */
+ public MessageLite getMessageDefaultInstance() {
+ return messageDefaultInstance;
+ }
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/Internal.java b/java/src/main/java/com/google/protobuf/Internal.java
new file mode 100644
index 00000000..ba8e6aee
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/Internal.java
@@ -0,0 +1,194 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * The classes contained within are used internally by the Protocol Buffer
+ * library and generated message implementations. They are public only because
+ * those generated messages do not reside in the {@code protobuf} package.
+ * Others should not use this class directly.
+ *
+ * @author cyrusn@google.com (Cyrus Najmabadi)
+ */
+public class Internal {
+ /**
+ * Implementation of a Queue designed to have as little overhead as possible.
+ * No guarantees are made as to the order you will get values back from the
+ * queue. Currently it is a Last-In-First-Out implementation, but that may
+ * change in the future.
+ *
+ * Duplicate values are allowed, as are null values.
+ *
+ * Not threadsafe.
+ *
+ * @author cyrusn@google.com (Cyrus Najmabadi)
+ */
+ public static final class QuickQueue<T> {
+ @SuppressWarnings("unchecked")
+ private T[] array = (T[]) new Object[16];
+ private int size;
+
+ /**
+ * Adds a value to the queue.
+ *
+ * @param value The value to add to the queue.
+ */
+ public void offer(final T value) {
+ if (size == array.length) {
+ // I'd like to use Arrays.copy here. However, it is currently
+ // unavailable
+ // on android. So, for now, we just use the tried and true arraycopy
+ // technique.
+ @SuppressWarnings("unchecked")
+ final T[] copy = (T[]) new Object[size * 2];
+ System.arraycopy(array, 0, copy, 0, array.length);
+ array = copy;
+ }
+
+ array[size++] = value;
+ }
+
+ /**
+ * Removes some previously added value to the queue, or {@code null} if the
+ * queue is empty.
+ *
+ * @return An existing value in the queue, or {@code null} if the queue is
+ * empty.
+ */
+ public T poll() {
+ if (size == 0) {
+ return null;
+ }
+
+ final T result = array[--size];
+ // make sure we null out the entry so that we're not keeping anything
+ // alive unnecessarily.
+ array[size] = null;
+
+ return result;
+ }
+ }
+
+ /**
+ * Instances of this class will provide a unique {@code QuickQueue} to each
+ * thread that accesses it. Very useful for providing free lists without
+ * needing to take any locks.
+ *
+ * @author cyrusn@google.com (Cyrus Najmabadi)
+ */
+ public static final class ThreadLocalQuickQueue<T>
+ extends ThreadLocal<QuickQueue<T>> {
+ @Override
+ protected QuickQueue<T> initialValue() {
+ return new QuickQueue<T>();
+ }
+ }
+
+ /**
+ * Helper called by generated code to construct default values for string
+ * fields.
+ * <p>
+ * The protocol compiler does not actually contain a UTF-8 decoder -- it
+ * just pushes UTF-8-encoded text around without touching it. The one place
+ * where this presents a problem is when generating Java string literals.
+ * Unicode characters in the string literal would normally need to be encoded
+ * using a Unicode escape sequence, which would require decoding them.
+ * To get around this, protoc instead embeds the UTF-8 bytes into the
+ * generated code and leaves it to the runtime library to decode them.
+ * <p>
+ * It gets worse, though. If protoc just generated a byte array, like:
+ * new byte[] {0x12, 0x34, 0x56, 0x78}
+ * Java actually generates *code* which allocates an array and then fills
+ * in each value. This is much less efficient than just embedding the bytes
+ * directly into the bytecode. To get around this, we need another
+ * work-around. String literals are embedded directly, so protoc actually
+ * generates a string literal corresponding to the bytes. The easiest way
+ * to do this is to use the ISO-8859-1 character set, which corresponds to
+ * the first 256 characters of the Unicode range. Protoc can then use
+ * good old CEscape to generate the string.
+ * <p>
+ * So we have a string literal which represents a set of bytes which
+ * represents another string. This function -- stringDefaultValue --
+ * converts from the generated string to the string we actually want. The
+ * generated code calls this automatically.
+ */
+ public static String stringDefaultValue(String bytes) {
+ try {
+ return new String(bytes.getBytes("ISO-8859-1"), "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ // This should never happen since all JVMs are required to implement
+ // both of the above character sets.
+ throw new IllegalStateException(
+ "Java VM does not support a standard character set.", e);
+ }
+ }
+
+ /**
+ * Helper called by generated code to construct default values for bytes
+ * fields.
+ * <p>
+ * This is a lot like {@link #stringDefaultValue}, but for bytes fields.
+ * In this case we only need the second of the two hacks -- allowing us to
+ * embed raw bytes as a string literal with ISO-8859-1 encoding.
+ */
+ public static ByteString bytesDefaultValue(String bytes) {
+ try {
+ return ByteString.copyFrom(bytes.getBytes("ISO-8859-1"));
+ } catch (UnsupportedEncodingException e) {
+ // This should never happen since all JVMs are required to implement
+ // ISO-8859-1.
+ throw new IllegalStateException(
+ "Java VM does not support a standard character set.", e);
+ }
+ }
+
+ /**
+ * Interface for an enum value or value descriptor, to be used in FieldSet.
+ * The lite library stores enum values directly in FieldSets but the full
+ * library stores EnumValueDescriptors in order to better support reflection.
+ */
+ public interface EnumLite {
+ int getNumber();
+ }
+
+ /**
+ * Interface for an object which maps integers to {@link EnumLite}s.
+ * {@link Descriptors.EnumDescriptor} implements this interface by mapping
+ * numbers to {@link Descriptors.EnumValueDescriptor}s. Additionally,
+ * every generated enum type has a static method internalGetValueMap() which
+ * returns an implementation of this type that maps numbers to enum values.
+ */
+ public interface EnumLiteMap<T extends EnumLite> {
+ T findValueByNumber(int number);
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java b/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
index 593be0e9..90f7ffbc 100644
--- a/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
+++ b/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
@@ -39,7 +39,9 @@ import java.io.IOException;
* @author kenton@google.com Kenton Varda
*/
public class InvalidProtocolBufferException extends IOException {
- public InvalidProtocolBufferException(String description) {
+ private static final long serialVersionUID = -1616151763072450476L;
+
+ public InvalidProtocolBufferException(final String description) {
super(description);
}
diff --git a/java/src/main/java/com/google/protobuf/Message.java b/java/src/main/java/com/google/protobuf/Message.java
index a5951232..c11abdc5 100644
--- a/java/src/main/java/com/google/protobuf/Message.java
+++ b/java/src/main/java/com/google/protobuf/Message.java
@@ -33,17 +33,22 @@
package com.google.protobuf;
-import java.io.InputStream;
import java.io.IOException;
-import java.io.OutputStream;
+import java.io.InputStream;
import java.util.Map;
/**
* Abstract interface implemented by Protocol Message objects.
+ * <p>
+ * See also {@link MessageLite}, which defines most of the methods that typical
+ * users care about. {@link Message} adds to it methods that are not available
+ * in the "lite" runtime. The biggest added features are introspection and
+ * reflection -- i.e., getting descriptors for the message type and accessing
+ * the field values dynamically.
*
* @author kenton@google.com Kenton Varda
*/
-public interface Message {
+public interface Message extends MessageLite {
/**
* Get the message's type's descriptor. This differs from the
* {@code getDescriptor()} method of generated message classes in that
@@ -53,14 +58,7 @@ public interface Message {
*/
Descriptors.Descriptor getDescriptorForType();
- /**
- * Get an instance of the type with all fields set to their default values.
- * This may or may not be a singleton. This differs from the
- * {@code getDefaultInstance()} method of generated message classes in that
- * this method is an abstract method of the {@code Message} interface
- * whereas {@code getDefaultInstance()} is a static method of a specific
- * class. They return the same thing.
- */
+ // (From MessageLite, re-declared here only for return type covariance.)
Message getDefaultInstanceForType();
/**
@@ -114,24 +112,6 @@ public interface Message {
/** Get the {@link UnknownFieldSet} for this message. */
UnknownFieldSet getUnknownFields();
- /**
- * Returns true if all required fields in the message and all embedded
- * messages are set, false otherwise.
- */
- boolean isInitialized();
-
- /**
- * Serializes the message and writes it to {@code output}. This does not
- * flush or close the stream.
- */
- void writeTo(CodedOutputStream output) throws IOException;
-
- /**
- * Get the number of bytes required to encode this message. The result
- * is only computed on the first call and memoized after that.
- */
- int getSerializedSize();
-
// -----------------------------------------------------------------
// Comparison and hashing
@@ -144,6 +124,7 @@ public interface Message {
* @param other object to be compared for equality with this message
* @return <tt>true</tt> if the specified object is equal to this message
*/
+ @Override
boolean equals(Object other);
/**
@@ -154,6 +135,7 @@ public interface Message {
* @return the hash code value for this message
* @see Map#hashCode()
*/
+ @Override
int hashCode();
// -----------------------------------------------------------------
@@ -163,67 +145,22 @@ public interface Message {
* Converts the message to a string in protocol buffer text format. This is
* just a trivial wrapper around {@link TextFormat#printToString(Message)}.
*/
+ @Override
String toString();
- /**
- * Serializes the message to a {@code ByteString} and returns it. This is
- * just a trivial wrapper around
- * {@link #writeTo(CodedOutputStream)}.
- */
- ByteString toByteString();
-
- /**
- * Serializes the message to a {@code byte} array and returns it. This is
- * just a trivial wrapper around
- * {@link #writeTo(CodedOutputStream)}.
- */
- byte[] toByteArray();
-
- /**
- * Serializes the message and writes it to {@code output}. This is just a
- * trivial wrapper around {@link #writeTo(CodedOutputStream)}. This does
- * not flush or close the stream.
- * <p>
- * NOTE: Protocol Buffers are not self-delimiting. Therefore, if you write
- * any more data to the stream after the message, you must somehow ensure
- * that the parser on the receiving end does not interpret this as being
- * part of the protocol message. This can be done e.g. by writing the size
- * of the message before the data, then making sure to limit the input to
- * that size on the receiving end (e.g. by wrapping the InputStream in one
- * which limits the input). Alternatively, just use
- * {@link #writeDelimitedTo(OutputStream)}.
- */
- void writeTo(OutputStream output) throws IOException;
-
- /**
- * Like {@link #writeTo(OutputStream)}, but writes the size of the message
- * as a varint before writing the data. This allows more data to be written
- * to the stream after the message without the need to delimit the message
- * data yourself. Use {@link Builder#mergeDelimitedFrom(InputStream)} (or
- * the static method {@code YourMessageType.parseDelimitedFrom(InputStream)})
- * to parse messages written by this method.
- */
- void writeDelimitedTo(OutputStream output) throws IOException;
-
// =================================================================
// Builders
- /**
- * Constructs a new builder for a message of the same type as this message.
- */
+ // (From MessageLite, re-declared here only for return type covariance.)
Builder newBuilderForType();
-
- /**
- * Constructs a builder initialized with the current message. Use this to
- * derive a new message from the current one.
- */
Builder toBuilder();
/**
* Abstract interface implemented by Protocol Message builders.
*/
- public static interface Builder extends Cloneable {
- /** Resets all fields to their default values. */
+ interface Builder extends MessageLite.Builder {
+ // (From MessageLite.Builder, re-declared here only for return type
+ // covariance.)
Builder clear();
/**
@@ -244,71 +181,14 @@ public interface Message {
*/
Builder mergeFrom(Message other);
- /**
- * Construct the final message. Once this is called, the Builder is no
- * longer valid, and calling any other method may throw a
- * NullPointerException. If you need to continue working with the builder
- * after calling {@code build()}, {@code clone()} it first.
- * @throws UninitializedMessageException The message is missing one or more
- * required fields (i.e. {@link #isInitialized()} returns false).
- * Use {@link #buildPartial()} to bypass this check.
- */
+ // (From MessageLite.Builder, re-declared here only for return type
+ // covariance.)
Message build();
-
- /**
- * Like {@link #build()}, but does not throw an exception if the message
- * is missing required fields. Instead, a partial message is returned.
- */
Message buildPartial();
-
- /**
- * Clones the Builder.
- * @see Object#clone()
- */
Builder clone();
-
- /**
- * Returns true if all required fields in the message and all embedded
- * messages are set, false otherwise.
- */
- boolean isInitialized();
-
- /**
- * Parses a message of this type from the input and merges it with this
- * message, as if using {@link Builder#mergeFrom(Message)}.
- *
- * <p>Warning: This does not verify that all required fields are present in
- * the input message. If you call {@link #build()} without setting all
- * required fields, it will throw an {@link UninitializedMessageException},
- * which is a {@code RuntimeException} and thus might not be caught. There
- * are a few good ways to deal with this:
- * <ul>
- * <li>Call {@link #isInitialized()} to verify that all required fields
- * are set before building.
- * <li>Parse the message separately using one of the static
- * {@code parseFrom} methods, then use {@link #mergeFrom(Message)}
- * to merge it with this one. {@code parseFrom} will throw an
- * {@link InvalidProtocolBufferException} (an {@code IOException})
- * if some required fields are missing.
- * <li>Use {@code buildPartial()} to build, which ignores missing
- * required fields.
- * </ul>
- *
- * <p>Note: The caller should call
- * {@link CodedInputStream#checkLastTagWas(int)} after calling this to
- * verify that the last tag seen was the appropriate end-group tag,
- * or zero for EOF.
- */
Builder mergeFrom(CodedInputStream input) throws IOException;
-
- /**
- * Like {@link Builder#mergeFrom(CodedInputStream)}, but also
- * parses extensions. The extensions that you want to be able to parse
- * must be registered in {@code extensionRegistry}. Extensions not in
- * the registry will be treated as unknown fields.
- */
Builder mergeFrom(CodedInputStream input,
- ExtensionRegistry extensionRegistry)
+ ExtensionRegistryLite extensionRegistry)
throws IOException;
/**
@@ -317,10 +197,8 @@ public interface Message {
*/
Descriptors.Descriptor getDescriptorForType();
- /**
- * Get the message's type's default instance.
- * See {@link Message#getDefaultInstanceForType()}.
- */
+ // (From MessageLite.Builder, re-declared here only for return type
+ // covariance.)
Message getDefaultInstanceForType();
/**
@@ -399,92 +277,29 @@ public interface Message {
// ---------------------------------------------------------------
// Convenience methods.
- /**
- * Parse {@code data} as a message of this type and merge it with the
- * message being built. This is just a small wrapper around
- * {@link #mergeFrom(CodedInputStream)}.
- */
+ // (From MessageLite.Builder, re-declared here only for return type
+ // covariance.)
Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException;
-
- /**
- * Parse {@code data} as a message of this type and merge it with the
- * message being built. This is just a small wrapper around
- * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
- */
Builder mergeFrom(ByteString data,
- ExtensionRegistry extensionRegistry)
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+ Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException;
+ Builder mergeFrom(byte[] data, int off, int len)
throws InvalidProtocolBufferException;
-
- /**
- * Parse {@code data} as a message of this type and merge it with the
- * message being built. This is just a small wrapper around
- * {@link #mergeFrom(CodedInputStream)}.
- */
- public Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException;
-
- /**
- * Parse {@code data} as a message of this type and merge it with the
- * message being built. This is just a small wrapper around
- * {@link #mergeFrom(CodedInputStream)}.
- */
- public Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException;
-
- /**
- * Parse {@code data} as a message of this type and merge it with the
- * message being built. This is just a small wrapper around
- * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
- */
Builder mergeFrom(byte[] data,
- ExtensionRegistry extensionRegistry)
+ ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException;
-
- /**
- * Parse {@code data} as a message of this type and merge it with the
- * message being built. This is just a small wrapper around
- * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
- */
Builder mergeFrom(byte[] data, int off, int len,
- ExtensionRegistry extensionRegistry)
+ ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException;
-
- /**
- * Parse a message of this type from {@code input} and merge it with the
- * message being built. This is just a small wrapper around
- * {@link #mergeFrom(CodedInputStream)}. Note that this method always
- * reads the <i>entire</i> input (unless it throws an exception). If you
- * want it to stop earlier, you will need to wrap your input in some
- * wrapper stream that limits reading. Or, use
- * {@link Message#writeDelimitedTo(OutputStream)} to write your message and
- * {@link #mergeDelimitedFrom(InputStream)} to read it.
- * <p>
- * Despite usually reading the entire input, this does not close the stream.
- */
Builder mergeFrom(InputStream input) throws IOException;
-
- /**
- * Parse a message of this type from {@code input} and merge it with the
- * message being built. This is just a small wrapper around
- * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
- */
Builder mergeFrom(InputStream input,
- ExtensionRegistry extensionRegistry)
+ ExtensionRegistryLite extensionRegistry)
throws IOException;
-
- /**
- * Like {@link #mergeFrom(InputStream)}, but does not read until EOF.
- * Instead, the size of the message (encoded as a varint) is read first,
- * then the message data. Use
- * {@link Message#writeDelimitedTo(OutputStream)} to write messages in this
- * format.
- */
Builder mergeDelimitedFrom(InputStream input)
throws IOException;
-
- /**
- * Like {@link #mergeDelimitedFrom(InputStream)} but supporting extensions.
- */
Builder mergeDelimitedFrom(InputStream input,
- ExtensionRegistry extensionRegistry)
+ ExtensionRegistryLite extensionRegistry)
throws IOException;
}
}
diff --git a/java/src/main/java/com/google/protobuf/MessageLite.java b/java/src/main/java/com/google/protobuf/MessageLite.java
new file mode 100644
index 00000000..3001f360
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/MessageLite.java
@@ -0,0 +1,331 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// TODO(kenton): Use generics? E.g. Builder<BuilderType extends Builder>, then
+// mergeFrom*() could return BuilderType for better type-safety.
+
+package com.google.protobuf;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Abstract interface implemented by Protocol Message objects.
+ *
+ * <p>This interface is implemented by all protocol message objects. Most
+ * users will be more interested in the Message interface, which is a subclass
+ * of MessageLite. Use MessageLite instead when you only need the subset of
+ * features which it supports -- namely, nothing that uses descriptors or
+ * reflection. You can instruct the protocol compiler to generate classes
+ * which implement only MessageLite, not the full Message interface, by adding
+ * the follow line to the .proto file:
+ * <pre>
+ * option optimize_for = LITE_RUNTIME;
+ * </pre>
+ *
+ * <p>This is particularly useful on resource-constrained systems where the
+ * full protocol buffers runtime library is too big.
+ *
+ * <p>Note that on non-constrained systems (e.g. servers) when you need to link
+ * in lots of protocol definitions, a better way to reduce total code footprint
+ * is to use {@code optimize_for = CODE_SIZE}. This will make the generated
+ * code smaller while still supporting all the same features (at the expense of
+ * speed). {@code optimize_for = LITE_RUNTIME} is best when you only have a
+ * small number of message types linked into your binary, in which case the
+ * size of the protocol buffers runtime itself is the biggest problem.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public interface MessageLite {
+ /**
+ * Get an instance of the type with all fields set to their default values.
+ * This may or may not be a singleton. This differs from the
+ * {@code getDefaultInstance()} method of generated message classes in that
+ * this method is an abstract method of the {@code MessageLite} interface
+ * whereas {@code getDefaultInstance()} is a static method of a specific
+ * class. They return the same thing.
+ */
+ MessageLite getDefaultInstanceForType();
+
+ /**
+ * Returns true if all required fields in the message and all embedded
+ * messages are set, false otherwise.
+ */
+ boolean isInitialized();
+
+ /**
+ * Serializes the message and writes it to {@code output}. This does not
+ * flush or close the stream.
+ */
+ void writeTo(CodedOutputStream output) throws IOException;
+
+ /**
+ * Get the number of bytes required to encode this message. The result
+ * is only computed on the first call and memoized after that.
+ */
+ int getSerializedSize();
+
+ // -----------------------------------------------------------------
+ // Convenience methods.
+
+ /**
+ * Serializes the message to a {@code ByteString} and returns it. This is
+ * just a trivial wrapper around
+ * {@link #writeTo(CodedOutputStream)}.
+ */
+ ByteString toByteString();
+
+ /**
+ * Serializes the message to a {@code byte} array and returns it. This is
+ * just a trivial wrapper around
+ * {@link #writeTo(CodedOutputStream)}.
+ */
+ byte[] toByteArray();
+
+ /**
+ * Serializes the message and writes it to {@code output}. This is just a
+ * trivial wrapper around {@link #writeTo(CodedOutputStream)}. This does
+ * not flush or close the stream.
+ * <p>
+ * NOTE: Protocol Buffers are not self-delimiting. Therefore, if you write
+ * any more data to the stream after the message, you must somehow ensure
+ * that the parser on the receiving end does not interpret this as being
+ * part of the protocol message. This can be done e.g. by writing the size
+ * of the message before the data, then making sure to limit the input to
+ * that size on the receiving end (e.g. by wrapping the InputStream in one
+ * which limits the input). Alternatively, just use
+ * {@link #writeDelimitedTo(OutputStream)}.
+ */
+ void writeTo(OutputStream output) throws IOException;
+
+ /**
+ * Like {@link #writeTo(OutputStream)}, but writes the size of the message
+ * as a varint before writing the data. This allows more data to be written
+ * to the stream after the message without the need to delimit the message
+ * data yourself. Use {@link Builder#mergeDelimitedFrom(InputStream)} (or
+ * the static method {@code YourMessageType.parseDelimitedFrom(InputStream)})
+ * to parse messages written by this method.
+ */
+ void writeDelimitedTo(OutputStream output) throws IOException;
+
+ // =================================================================
+ // Builders
+
+ /**
+ * Constructs a new builder for a message of the same type as this message.
+ */
+ Builder newBuilderForType();
+
+ /**
+ * Constructs a builder initialized with the current message. Use this to
+ * derive a new message from the current one.
+ */
+ Builder toBuilder();
+
+ /**
+ * Abstract interface implemented by Protocol Message builders.
+ */
+ interface Builder extends Cloneable {
+ /** Resets all fields to their default values. */
+ Builder clear();
+
+ /**
+ * Construct the final message. Once this is called, the Builder is no
+ * longer valid, and calling any other method will result in undefined
+ * behavior and may throw a NullPointerException. If you need to continue
+ * working with the builder after calling {@code build()}, {@code clone()}
+ * it first.
+ * @throws UninitializedMessageException The message is missing one or more
+ * required fields (i.e. {@link #isInitialized()} returns false).
+ * Use {@link #buildPartial()} to bypass this check.
+ */
+ MessageLite build();
+
+ /**
+ * Like {@link #build()}, but does not throw an exception if the message
+ * is missing required fields. Instead, a partial message is returned.
+ * Once this is called, the Builder is no longer valid, and calling any
+ * will result in undefined behavior and may throw a NullPointerException.
+ *
+ * If you need to continue working with the builder after calling
+ * {@code buildPartial()}, {@code clone()} it first.
+ */
+ MessageLite buildPartial();
+
+ /**
+ * Clones the Builder.
+ * @see Object#clone()
+ */
+ Builder clone();
+
+ /**
+ * Returns true if all required fields in the message and all embedded
+ * messages are set, false otherwise.
+ */
+ boolean isInitialized();
+
+ /**
+ * Parses a message of this type from the input and merges it with this
+ * message, as if using {@link Builder#mergeFrom(MessageLite)}.
+ *
+ * <p>Warning: This does not verify that all required fields are present in
+ * the input message. If you call {@link #build()} without setting all
+ * required fields, it will throw an {@link UninitializedMessageException},
+ * which is a {@code RuntimeException} and thus might not be caught. There
+ * are a few good ways to deal with this:
+ * <ul>
+ * <li>Call {@link #isInitialized()} to verify that all required fields
+ * are set before building.
+ * <li>Parse the message separately using one of the static
+ * {@code parseFrom} methods, then use {@link #mergeFrom(MessageLite)}
+ * to merge it with this one. {@code parseFrom} will throw an
+ * {@link InvalidProtocolBufferException} (an {@code IOException})
+ * if some required fields are missing.
+ * <li>Use {@code buildPartial()} to build, which ignores missing
+ * required fields.
+ * </ul>
+ *
+ * <p>Note: The caller should call
+ * {@link CodedInputStream#checkLastTagWas(int)} after calling this to
+ * verify that the last tag seen was the appropriate end-group tag,
+ * or zero for EOF.
+ */
+ Builder mergeFrom(CodedInputStream input) throws IOException;
+
+ /**
+ * Like {@link Builder#mergeFrom(CodedInputStream)}, but also
+ * parses extensions. The extensions that you want to be able to parse
+ * must be registered in {@code extensionRegistry}. Extensions not in
+ * the registry will be treated as unknown fields.
+ */
+ Builder mergeFrom(CodedInputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws IOException;
+
+ /**
+ * Get the message's type's default instance.
+ * See {@link MessageLite#getDefaultInstanceForType()}.
+ */
+ MessageLite getDefaultInstanceForType();
+
+ // ---------------------------------------------------------------
+ // Convenience methods.
+
+ /**
+ * Parse {@code data} as a message of this type and merge it with the
+ * message being built. This is just a small wrapper around
+ * {@link #mergeFrom(CodedInputStream)}.
+ */
+ Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException;
+
+ /**
+ * Parse {@code data} as a message of this type and merge it with the
+ * message being built. This is just a small wrapper around
+ * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
+ */
+ Builder mergeFrom(ByteString data,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Parse {@code data} as a message of this type and merge it with the
+ * message being built. This is just a small wrapper around
+ * {@link #mergeFrom(CodedInputStream)}.
+ */
+ Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException;
+
+ /**
+ * Parse {@code data} as a message of this type and merge it with the
+ * message being built. This is just a small wrapper around
+ * {@link #mergeFrom(CodedInputStream)}.
+ */
+ Builder mergeFrom(byte[] data, int off, int len)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Parse {@code data} as a message of this type and merge it with the
+ * message being built. This is just a small wrapper around
+ * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
+ */
+ Builder mergeFrom(byte[] data,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Parse {@code data} as a message of this type and merge it with the
+ * message being built. This is just a small wrapper around
+ * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
+ */
+ Builder mergeFrom(byte[] data, int off, int len,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Parse a message of this type from {@code input} and merge it with the
+ * message being built. This is just a small wrapper around
+ * {@link #mergeFrom(CodedInputStream)}. Note that this method always
+ * reads the <i>entire</i> input (unless it throws an exception). If you
+ * want it to stop earlier, you will need to wrap your input in some
+ * wrapper stream that limits reading. Or, use
+ * {@link MessageLite#writeDelimitedTo(OutputStream)} to write your message
+ * and {@link #mergeDelimitedFrom(InputStream)} to read it.
+ * <p>
+ * Despite usually reading the entire input, this does not close the stream.
+ */
+ Builder mergeFrom(InputStream input) throws IOException;
+
+ /**
+ * Parse a message of this type from {@code input} and merge it with the
+ * message being built. This is just a small wrapper around
+ * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
+ */
+ Builder mergeFrom(InputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws IOException;
+
+ /**
+ * Like {@link #mergeFrom(InputStream)}, but does not read until EOF.
+ * Instead, the size of the message (encoded as a varint) is read first,
+ * then the message data. Use
+ * {@link MessageLite#writeDelimitedTo(OutputStream)} to write messages in
+ * this format.
+ */
+ Builder mergeDelimitedFrom(InputStream input)
+ throws IOException;
+
+ /**
+ * Like {@link #mergeDelimitedFrom(InputStream)} but supporting extensions.
+ */
+ Builder mergeDelimitedFrom(InputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws IOException;
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java b/java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java
index 8efca8af..112400f4 100644
--- a/java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java
+++ b/java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java
@@ -37,7 +37,7 @@ import com.google.protobuf.Descriptors.EnumValueDescriptor;
* Interface of useful methods added to all enums generated by the protocol
* compiler.
*/
-public interface ProtocolMessageEnum {
+public interface ProtocolMessageEnum extends Internal.EnumLite {
/**
* Return the value's numeric value as defined in the .proto file.
diff --git a/java/src/main/java/com/google/protobuf/RpcUtil.java b/java/src/main/java/com/google/protobuf/RpcUtil.java
index 8144bbfb..b1b959a8 100644
--- a/java/src/main/java/com/google/protobuf/RpcUtil.java
+++ b/java/src/main/java/com/google/protobuf/RpcUtil.java
@@ -71,11 +71,11 @@ public final class RpcUtil {
final Class<Type> originalClass,
final Type defaultInstance) {
return new RpcCallback<Message>() {
- public void run(Message parameter) {
+ public void run(final Message parameter) {
Type typedParameter;
try {
typedParameter = originalClass.cast(parameter);
- } catch (ClassCastException e) {
+ } catch (ClassCastException ignored) {
typedParameter = copyAsType(defaultInstance, parameter);
}
originalCallback.run(typedParameter);
@@ -90,7 +90,7 @@ public final class RpcUtil {
*/
@SuppressWarnings("unchecked")
private static <Type extends Message> Type copyAsType(
- Type typeDefaultInstance, Message source) {
+ final Type typeDefaultInstance, final Message source) {
return (Type)typeDefaultInstance.newBuilderForType()
.mergeFrom(source)
.build();
@@ -106,8 +106,9 @@ public final class RpcUtil {
RpcCallback<ParameterType> newOneTimeCallback(
final RpcCallback<ParameterType> originalCallback) {
return new RpcCallback<ParameterType>() {
- boolean alreadyCalled = false;
- public void run(ParameterType parameter) {
+ private boolean alreadyCalled = false;
+
+ public void run(final ParameterType parameter) {
synchronized(this) {
if (alreadyCalled) {
throw new AlreadyCalledException();
@@ -124,6 +125,8 @@ public final class RpcUtil {
* Exception thrown when a one-time callback is called more than once.
*/
public static final class AlreadyCalledException extends RuntimeException {
+ private static final long serialVersionUID = 5469741279507848266L;
+
public AlreadyCalledException() {
super("This RpcCallback was already called and cannot be called " +
"multiple times.");
diff --git a/java/src/main/java/com/google/protobuf/ServiceException.java b/java/src/main/java/com/google/protobuf/ServiceException.java
index 70b9d0c1..c043a775 100644
--- a/java/src/main/java/com/google/protobuf/ServiceException.java
+++ b/java/src/main/java/com/google/protobuf/ServiceException.java
@@ -32,11 +32,13 @@ package com.google.protobuf;
/**
* Thrown by blocking RPC methods when a failure occurs.
- *
+ *
* @author cpovirk@google.com (Chris Povirk)
*/
public final class ServiceException extends Exception {
- public ServiceException(String message) {
+ private static final long serialVersionUID = -1219262335729891920L;
+
+ public ServiceException(final String message) {
super(message);
}
}
diff --git a/java/src/main/java/com/google/protobuf/TextFormat.java b/java/src/main/java/com/google/protobuf/TextFormat.java
index 3dcf68c8..a855720b 100644
--- a/java/src/main/java/com/google/protobuf/TextFormat.java
+++ b/java/src/main/java/com/google/protobuf/TextFormat.java
@@ -52,22 +52,25 @@ import java.util.regex.Pattern;
* @author kenton@google.com Kenton Varda
*/
public final class TextFormat {
+ private TextFormat() {
+ }
/**
* Outputs a textual representation of the Protocol Message supplied into
* the parameter output. (This representation is the new version of the
* classic "ProtocolPrinter" output from the original Protocol Buffer system)
*/
- public static void print(Message message, Appendable output)
+ public static void print(final Message message, final Appendable output)
throws IOException {
- TextGenerator generator = new TextGenerator(output);
+ final TextGenerator generator = new TextGenerator(output);
print(message, generator);
}
/** Outputs a textual representation of {@code fields} to {@code output}. */
- public static void print(UnknownFieldSet fields, Appendable output)
+ public static void print(final UnknownFieldSet fields,
+ final Appendable output)
throws IOException {
- TextGenerator generator = new TextGenerator(output);
+ final TextGenerator generator = new TextGenerator(output);
printUnknownFields(fields, generator);
}
@@ -75,9 +78,9 @@ public final class TextFormat {
* Like {@code print()}, but writes directly to a {@code String} and
* returns it.
*/
- public static String printToString(Message message) {
+ public static String printToString(final Message message) {
try {
- StringBuilder text = new StringBuilder();
+ final StringBuilder text = new StringBuilder();
print(message, text);
return text.toString();
} catch (IOException e) {
@@ -91,9 +94,9 @@ public final class TextFormat {
* Like {@code print()}, but writes directly to a {@code String} and
* returns it.
*/
- public static String printToString(UnknownFieldSet fields) {
+ public static String printToString(final UnknownFieldSet fields) {
try {
- StringBuilder text = new StringBuilder();
+ final StringBuilder text = new StringBuilder();
print(fields, text);
return text.toString();
} catch (IOException e) {
@@ -103,22 +106,44 @@ public final class TextFormat {
}
}
- private static void print(Message message, TextGenerator generator)
+ private static void print(final Message message,
+ final TextGenerator generator)
throws IOException {
- for (Map.Entry<FieldDescriptor, Object> field :
+ for (final Map.Entry<FieldDescriptor, Object> field :
message.getAllFields().entrySet()) {
printField(field.getKey(), field.getValue(), generator);
}
printUnknownFields(message.getUnknownFields(), generator);
}
+
+ public static void printField(final FieldDescriptor field,
+ final Object value,
+ final Appendable output)
+ throws IOException {
+ final TextGenerator generator = new TextGenerator(output);
+ printField(field, value, generator);
+ }
- public static void printField(FieldDescriptor field,
- Object value,
- TextGenerator generator)
+ public static String printFieldToString(final FieldDescriptor field,
+ final Object value) {
+ try {
+ final StringBuilder text = new StringBuilder();
+ printField(field, value, text);
+ return text.toString();
+ } catch (IOException e) {
+ throw new RuntimeException(
+ "Writing to a StringBuilder threw an IOException (should never " +
+ "happen).", e);
+ }
+ }
+
+ private static void printField(final FieldDescriptor field,
+ final Object value,
+ final TextGenerator generator)
throws IOException {
if (field.isRepeated()) {
// Repeated field. Print each element.
- for (Object element : (List) value) {
+ for (final Object element : (List) value) {
printSingleField(field, element, generator);
}
} else {
@@ -126,9 +151,9 @@ public final class TextFormat {
}
}
- private static void printSingleField(FieldDescriptor field,
- Object value,
- TextGenerator generator)
+ private static void printSingleField(final FieldDescriptor field,
+ final Object value,
+ final TextGenerator generator)
throws IOException {
if (field.isExtension()) {
generator.print("[");
@@ -168,9 +193,9 @@ public final class TextFormat {
generator.print("\n");
}
- private static void printFieldValue(FieldDescriptor field,
- Object value,
- TextGenerator generator)
+ private static void printFieldValue(final FieldDescriptor field,
+ final Object value,
+ final TextGenerator generator)
throws IOException {
switch (field.getType()) {
case INT32:
@@ -202,17 +227,15 @@ public final class TextFormat {
generator.print("\"");
break;
- case BYTES: {
+ case BYTES:
generator.print("\"");
generator.print(escapeBytes((ByteString) value));
generator.print("\"");
break;
- }
- case ENUM: {
+ case ENUM:
generator.print(((EnumValueDescriptor) value).getName());
break;
- }
case MESSAGE:
case GROUP:
@@ -221,39 +244,39 @@ public final class TextFormat {
}
}
- private static void printUnknownFields(UnknownFieldSet unknownFields,
- TextGenerator generator)
+ private static void printUnknownFields(final UnknownFieldSet unknownFields,
+ final TextGenerator generator)
throws IOException {
- for (Map.Entry<Integer, UnknownFieldSet.Field> entry :
+ for (final Map.Entry<Integer, UnknownFieldSet.Field> entry :
unknownFields.asMap().entrySet()) {
- String prefix = entry.getKey().toString() + ": ";
- UnknownFieldSet.Field field = entry.getValue();
+ final String prefix = entry.getKey().toString() + ": ";
+ final UnknownFieldSet.Field field = entry.getValue();
- for (long value : field.getVarintList()) {
+ for (final long value : field.getVarintList()) {
generator.print(entry.getKey().toString());
generator.print(": ");
generator.print(unsignedToString(value));
generator.print("\n");
}
- for (int value : field.getFixed32List()) {
+ for (final int value : field.getFixed32List()) {
generator.print(entry.getKey().toString());
generator.print(": ");
generator.print(String.format((Locale) null, "0x%08x", value));
generator.print("\n");
}
- for (long value : field.getFixed64List()) {
+ for (final long value : field.getFixed64List()) {
generator.print(entry.getKey().toString());
generator.print(": ");
generator.print(String.format((Locale) null, "0x%016x", value));
generator.print("\n");
}
- for (ByteString value : field.getLengthDelimitedList()) {
+ for (final ByteString value : field.getLengthDelimitedList()) {
generator.print(entry.getKey().toString());
generator.print(": \"");
generator.print(escapeBytes(value));
generator.print("\"\n");
}
- for (UnknownFieldSet value : field.getGroupList()) {
+ for (final UnknownFieldSet value : field.getGroupList()) {
generator.print(entry.getKey().toString());
generator.print(" {\n");
generator.indent();
@@ -265,7 +288,7 @@ public final class TextFormat {
}
/** Convert an unsigned 32-bit integer to a string. */
- private static String unsignedToString(int value) {
+ private static String unsignedToString(final int value) {
if (value >= 0) {
return Integer.toString(value);
} else {
@@ -274,7 +297,7 @@ public final class TextFormat {
}
/** Convert an unsigned 64-bit integer to a string. */
- private static String unsignedToString(long value) {
+ private static String unsignedToString(final long value) {
if (value >= 0) {
return Long.toString(value);
} else {
@@ -288,13 +311,12 @@ public final class TextFormat {
/**
* An inner class for writing text to the output stream.
*/
- static private final class TextGenerator {
+ private static final class TextGenerator {
+ private Appendable output;
+ private boolean atStartOfLine = true;
+ private final StringBuilder indent = new StringBuilder();
- Appendable output;
- boolean atStartOfLine = true;
- StringBuilder indent = new StringBuilder();
-
- public TextGenerator(Appendable output) {
+ private TextGenerator(final Appendable output) {
this.output = output;
}
@@ -312,7 +334,7 @@ public final class TextFormat {
* level is zero.
*/
public void outdent() {
- int length = indent.length();
+ final int length = indent.length();
if (length == 0) {
throw new IllegalArgumentException(
" Outdent() without matching Indent().");
@@ -323,8 +345,8 @@ public final class TextFormat {
/**
* Print text to the output stream.
*/
- public void print(CharSequence text) throws IOException {
- int size = text.length();
+ public void print(final CharSequence text) throws IOException {
+ final int size = text.length();
int pos = 0;
for (int i = 0; i < size; i++) {
@@ -337,7 +359,8 @@ public final class TextFormat {
write(text.subSequence(pos, size), size - pos);
}
- private void write(CharSequence data, int size) throws IOException {
+ private void write(final CharSequence data, final int size)
+ throws IOException {
if (size == 0) {
return;
}
@@ -399,27 +422,27 @@ public final class TextFormat {
// We use possesive quantifiers (*+ and ++) because otherwise the Java
// regex matcher has stack overflows on large inputs.
- private static Pattern WHITESPACE =
+ private static final Pattern WHITESPACE =
Pattern.compile("(\\s|(#.*$))++", Pattern.MULTILINE);
- private static Pattern TOKEN = Pattern.compile(
+ private static final Pattern TOKEN = Pattern.compile(
"[a-zA-Z_][0-9a-zA-Z_+-]*+|" + // an identifier
"[0-9+-][0-9a-zA-Z_.+-]*+|" + // a number
"\"([^\"\n\\\\]|\\\\.)*+(\"|\\\\?$)|" + // a double-quoted string
"\'([^\"\n\\\\]|\\\\.)*+(\'|\\\\?$)", // a single-quoted string
Pattern.MULTILINE);
- private static Pattern DOUBLE_INFINITY = Pattern.compile(
+ private static final Pattern DOUBLE_INFINITY = Pattern.compile(
"-?inf(inity)?",
Pattern.CASE_INSENSITIVE);
- private static Pattern FLOAT_INFINITY = Pattern.compile(
+ private static final Pattern FLOAT_INFINITY = Pattern.compile(
"-?inf(inity)?f?",
Pattern.CASE_INSENSITIVE);
- private static Pattern FLOAT_NAN = Pattern.compile(
+ private static final Pattern FLOAT_NAN = Pattern.compile(
"nanf?",
Pattern.CASE_INSENSITIVE);
/** Construct a tokenizer that parses tokens from the given text. */
- public Tokenizer(CharSequence text) {
+ private Tokenizer(final CharSequence text) {
this.text = text;
this.matcher = WHITESPACE.matcher(text);
skipWhitespace();
@@ -481,7 +504,7 @@ public final class TextFormat {
* If the next token exactly matches {@code token}, consume it and return
* {@code true}. Otherwise, return {@code false} without doing anything.
*/
- public boolean tryConsume(String token) {
+ public boolean tryConsume(final String token) {
if (currentToken.equals(token)) {
nextToken();
return true;
@@ -494,7 +517,7 @@ public final class TextFormat {
* If the next token exactly matches {@code token}, consume it. Otherwise,
* throw a {@link ParseException}.
*/
- public void consume(String token) throws ParseException {
+ public void consume(final String token) throws ParseException {
if (!tryConsume(token)) {
throw parseException("Expected \"" + token + "\".");
}
@@ -509,7 +532,7 @@ public final class TextFormat {
return false;
}
- char c = currentToken.charAt(0);
+ final char c = currentToken.charAt(0);
return ('0' <= c && c <= '9') ||
c == '-' || c == '+';
}
@@ -520,7 +543,7 @@ public final class TextFormat {
*/
public String consumeIdentifier() throws ParseException {
for (int i = 0; i < currentToken.length(); i++) {
- char c = currentToken.charAt(i);
+ final char c = currentToken.charAt(i);
if (('a' <= c && c <= 'z') ||
('A' <= c && c <= 'Z') ||
('0' <= c && c <= '9') ||
@@ -531,7 +554,7 @@ public final class TextFormat {
}
}
- String result = currentToken;
+ final String result = currentToken;
nextToken();
return result;
}
@@ -542,7 +565,7 @@ public final class TextFormat {
*/
public int consumeInt32() throws ParseException {
try {
- int result = parseInt32(currentToken);
+ final int result = parseInt32(currentToken);
nextToken();
return result;
} catch (NumberFormatException e) {
@@ -556,7 +579,7 @@ public final class TextFormat {
*/
public int consumeUInt32() throws ParseException {
try {
- int result = parseUInt32(currentToken);
+ final int result = parseUInt32(currentToken);
nextToken();
return result;
} catch (NumberFormatException e) {
@@ -570,7 +593,7 @@ public final class TextFormat {
*/
public long consumeInt64() throws ParseException {
try {
- long result = parseInt64(currentToken);
+ final long result = parseInt64(currentToken);
nextToken();
return result;
} catch (NumberFormatException e) {
@@ -584,7 +607,7 @@ public final class TextFormat {
*/
public long consumeUInt64() throws ParseException {
try {
- long result = parseUInt64(currentToken);
+ final long result = parseUInt64(currentToken);
nextToken();
return result;
} catch (NumberFormatException e) {
@@ -600,7 +623,7 @@ public final class TextFormat {
// We need to parse infinity and nan separately because
// Double.parseDouble() does not accept "inf", "infinity", or "nan".
if (DOUBLE_INFINITY.matcher(currentToken).matches()) {
- boolean negative = currentToken.startsWith("-");
+ final boolean negative = currentToken.startsWith("-");
nextToken();
return negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
}
@@ -609,7 +632,7 @@ public final class TextFormat {
return Double.NaN;
}
try {
- double result = Double.parseDouble(currentToken);
+ final double result = Double.parseDouble(currentToken);
nextToken();
return result;
} catch (NumberFormatException e) {
@@ -625,7 +648,7 @@ public final class TextFormat {
// We need to parse infinity and nan separately because
// Float.parseFloat() does not accept "inf", "infinity", or "nan".
if (FLOAT_INFINITY.matcher(currentToken).matches()) {
- boolean negative = currentToken.startsWith("-");
+ final boolean negative = currentToken.startsWith("-");
nextToken();
return negative ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
}
@@ -634,7 +657,7 @@ public final class TextFormat {
return Float.NaN;
}
try {
- float result = Float.parseFloat(currentToken);
+ final float result = Float.parseFloat(currentToken);
nextToken();
return result;
} catch (NumberFormatException e) {
@@ -672,7 +695,8 @@ public final class TextFormat {
* {@link ParseException}.
*/
public ByteString consumeByteString() throws ParseException {
- char quote = currentToken.length() > 0 ? currentToken.charAt(0) : '\0';
+ final char quote = currentToken.length() > 0 ? currentToken.charAt(0)
+ : '\0';
if (quote != '\"' && quote != '\'') {
throw parseException("Expected string.");
}
@@ -683,11 +707,12 @@ public final class TextFormat {
}
try {
- String escaped = currentToken.substring(1, currentToken.length() - 1);
- ByteString result = unescapeBytes(escaped);
+ final String escaped =
+ currentToken.substring(1, currentToken.length() - 1);
+ final ByteString result = unescapeBytes(escaped);
nextToken();
return result;
- } catch (InvalidEscapeSequence e) {
+ } catch (InvalidEscapeSequenceException e) {
throw parseException(e.getMessage());
}
}
@@ -696,7 +721,7 @@ public final class TextFormat {
* Returns a {@link ParseException} with the current line and column
* numbers in the description, suitable for throwing.
*/
- public ParseException parseException(String description) {
+ public ParseException parseException(final String description) {
// Note: People generally prefer one-based line and column numbers.
return new ParseException(
(line + 1) + ":" + (column + 1) + ": " + description);
@@ -706,7 +731,8 @@ public final class TextFormat {
* Returns a {@link ParseException} with the line and column numbers of
* the previous token in the description, suitable for throwing.
*/
- public ParseException parseExceptionPreviousToken(String description) {
+ public ParseException parseExceptionPreviousToken(
+ final String description) {
// Note: People generally prefer one-based line and column numbers.
return new ParseException(
(previousLine + 1) + ":" + (previousColumn + 1) + ": " + description);
@@ -716,7 +742,8 @@ public final class TextFormat {
* Constructs an appropriate {@link ParseException} for the given
* {@code NumberFormatException} when trying to parse an integer.
*/
- private ParseException integerParseException(NumberFormatException e) {
+ private ParseException integerParseException(
+ final NumberFormatException e) {
return parseException("Couldn't parse integer: " + e.getMessage());
}
@@ -724,14 +751,16 @@ public final class TextFormat {
* Constructs an appropriate {@link ParseException} for the given
* {@code NumberFormatException} when trying to parse a float or double.
*/
- private ParseException floatParseException(NumberFormatException e) {
+ private ParseException floatParseException(final NumberFormatException e) {
return parseException("Couldn't parse number: " + e.getMessage());
}
}
/** Thrown when parsing an invalid text format message. */
public static class ParseException extends IOException {
- public ParseException(String message) {
+ private static final long serialVersionUID = 3196188060225107702L;
+
+ public ParseException(final String message) {
super(message);
}
}
@@ -740,9 +769,9 @@ public final class TextFormat {
* Parse a text-format message from {@code input} and merge the contents
* into {@code builder}.
*/
- public static void merge(Readable input,
- Message.Builder builder)
- throws ParseException, IOException {
+ public static void merge(final Readable input,
+ final Message.Builder builder)
+ throws IOException {
merge(input, ExtensionRegistry.getEmptyRegistry(), builder);
}
@@ -750,8 +779,8 @@ public final class TextFormat {
* Parse a text-format message from {@code input} and merge the contents
* into {@code builder}.
*/
- public static void merge(CharSequence input,
- Message.Builder builder)
+ public static void merge(final CharSequence input,
+ final Message.Builder builder)
throws ParseException {
merge(input, ExtensionRegistry.getEmptyRegistry(), builder);
}
@@ -761,10 +790,10 @@ public final class TextFormat {
* into {@code builder}. Extensions will be recognized if they are
* registered in {@code extensionRegistry}.
*/
- public static void merge(Readable input,
- ExtensionRegistry extensionRegistry,
- Message.Builder builder)
- throws ParseException, IOException {
+ public static void merge(final Readable input,
+ final ExtensionRegistry extensionRegistry,
+ final Message.Builder builder)
+ throws IOException {
// Read the entire input to a String then parse that.
// If StreamTokenizer were not quite so crippled, or if there were a kind
@@ -780,12 +809,12 @@ public final class TextFormat {
// TODO(chrisn): See if working around java.io.Reader#read(CharBuffer)
// overhead is worthwhile
- private static StringBuilder toStringBuilder(Readable input)
+ private static StringBuilder toStringBuilder(final Readable input)
throws IOException {
- StringBuilder text = new StringBuilder();
- CharBuffer buffer = CharBuffer.allocate(BUFFER_SIZE);
+ final StringBuilder text = new StringBuilder();
+ final CharBuffer buffer = CharBuffer.allocate(BUFFER_SIZE);
while (true) {
- int n = input.read(buffer);
+ final int n = input.read(buffer);
if (n == -1) {
break;
}
@@ -800,11 +829,11 @@ public final class TextFormat {
* into {@code builder}. Extensions will be recognized if they are
* registered in {@code extensionRegistry}.
*/
- public static void merge(CharSequence input,
- ExtensionRegistry extensionRegistry,
- Message.Builder builder)
+ public static void merge(final CharSequence input,
+ final ExtensionRegistry extensionRegistry,
+ final Message.Builder builder)
throws ParseException {
- Tokenizer tokenizer = new Tokenizer(input);
+ final Tokenizer tokenizer = new Tokenizer(input);
while (!tokenizer.atEnd()) {
mergeField(tokenizer, extensionRegistry, builder);
@@ -815,19 +844,20 @@ public final class TextFormat {
* Parse a single field from {@code tokenizer} and merge it into
* {@code builder}.
*/
- private static void mergeField(Tokenizer tokenizer,
- ExtensionRegistry extensionRegistry,
- Message.Builder builder)
+ private static void mergeField(final Tokenizer tokenizer,
+ final ExtensionRegistry extensionRegistry,
+ final Message.Builder builder)
throws ParseException {
FieldDescriptor field;
- Descriptor type = builder.getDescriptorForType();
+ final Descriptor type = builder.getDescriptorForType();
ExtensionRegistry.ExtensionInfo extension = null;
if (tokenizer.tryConsume("[")) {
// An extension.
- StringBuilder name = new StringBuilder(tokenizer.consumeIdentifier());
+ final StringBuilder name =
+ new StringBuilder(tokenizer.consumeIdentifier());
while (tokenizer.tryConsume(".")) {
- name.append(".");
+ name.append('.');
name.append(tokenizer.consumeIdentifier());
}
@@ -846,7 +876,7 @@ public final class TextFormat {
field = extension.descriptor;
} else {
- String name = tokenizer.consumeIdentifier();
+ final String name = tokenizer.consumeIdentifier();
field = type.findFieldByName(name);
// Group names are expected to be capitalized as they appear in the
@@ -855,7 +885,7 @@ public final class TextFormat {
if (field == null) {
// Explicitly specify US locale so that this code does not break when
// executing in Turkey.
- String lowerName = name.toLowerCase(Locale.US);
+ final String lowerName = name.toLowerCase(Locale.US);
field = type.findFieldByName(lowerName);
// If the case-insensitive match worked but the field is NOT a group,
if (field != null && field.getType() != FieldDescriptor.Type.GROUP) {
@@ -880,7 +910,7 @@ public final class TextFormat {
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
tokenizer.tryConsume(":"); // optional
- String endToken;
+ final String endToken;
if (tokenizer.tryConsume("<")) {
endToken = ">";
} else {
@@ -888,7 +918,7 @@ public final class TextFormat {
endToken = "}";
}
- Message.Builder subBuilder;
+ final Message.Builder subBuilder;
if (extension == null) {
subBuilder = builder.newBuilderForField(field);
} else {
@@ -951,19 +981,19 @@ public final class TextFormat {
value = tokenizer.consumeByteString();
break;
- case ENUM: {
- EnumDescriptor enumType = field.getEnumType();
+ case ENUM:
+ final EnumDescriptor enumType = field.getEnumType();
if (tokenizer.lookingAtInteger()) {
- int number = tokenizer.consumeInt32();
+ final int number = tokenizer.consumeInt32();
value = enumType.findValueByNumber(number);
if (value == null) {
throw tokenizer.parseExceptionPreviousToken(
"Enum type \"" + enumType.getFullName() +
- "\" has no value with number " + number + ".");
+ "\" has no value with number " + number + '.');
}
} else {
- String id = tokenizer.consumeIdentifier();
+ final String id = tokenizer.consumeIdentifier();
value = enumType.findValueByName(id);
if (value == null) {
throw tokenizer.parseExceptionPreviousToken(
@@ -973,7 +1003,6 @@ public final class TextFormat {
}
break;
- }
case MESSAGE:
case GROUP:
@@ -1002,10 +1031,10 @@ public final class TextFormat {
* which no defined short-hand escape sequence is defined will be escaped
* using 3-digit octal sequences.
*/
- static String escapeBytes(ByteString input) {
- StringBuilder builder = new StringBuilder(input.size());
+ static String escapeBytes(final ByteString input) {
+ final StringBuilder builder = new StringBuilder(input.size());
for (int i = 0; i < input.size(); i++) {
- byte b = input.byteAt(i);
+ final byte b = input.byteAt(i);
switch (b) {
// Java does not recognize \a or \v, apparently.
case 0x07: builder.append("\\a" ); break;
@@ -1038,9 +1067,9 @@ public final class TextFormat {
* {@link #escapeBytes(ByteString)}. Two-digit hex escapes (starting with
* "\x") are also recognized.
*/
- static ByteString unescapeBytes(CharSequence input)
- throws InvalidEscapeSequence {
- byte[] result = new byte[input.length()];
+ static ByteString unescapeBytes(final CharSequence input)
+ throws InvalidEscapeSequenceException {
+ final byte[] result = new byte[input.length()];
int pos = 0;
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
@@ -1080,7 +1109,7 @@ public final class TextFormat {
++i;
code = digitValue(input.charAt(i));
} else {
- throw new InvalidEscapeSequence(
+ throw new InvalidEscapeSequenceException(
"Invalid escape sequence: '\\x' with no digits");
}
if (i + 1 < input.length() && isHex(input.charAt(i + 1))) {
@@ -1091,12 +1120,12 @@ public final class TextFormat {
break;
default:
- throw new InvalidEscapeSequence(
- "Invalid escape sequence: '\\" + c + "'");
+ throw new InvalidEscapeSequenceException(
+ "Invalid escape sequence: '\\" + c + '\'');
}
}
} else {
- throw new InvalidEscapeSequence(
+ throw new InvalidEscapeSequenceException(
"Invalid escape sequence: '\\' at end of string.");
}
} else {
@@ -1111,8 +1140,10 @@ public final class TextFormat {
* Thrown by {@link TextFormat#unescapeBytes} and
* {@link TextFormat#unescapeText} when an invalid escape sequence is seen.
*/
- static class InvalidEscapeSequence extends IOException {
- public InvalidEscapeSequence(String description) {
+ static class InvalidEscapeSequenceException extends IOException {
+ private static final long serialVersionUID = -8164033650142593304L;
+
+ InvalidEscapeSequenceException(final String description) {
super(description);
}
}
@@ -1122,7 +1153,7 @@ public final class TextFormat {
* Non-ASCII characters are first encoded as UTF-8, then each byte is escaped
* individually as a 3-digit octal escape. Yes, it's weird.
*/
- static String escapeText(String input) {
+ static String escapeText(final String input) {
return escapeBytes(ByteString.copyFromUtf8(input));
}
@@ -1130,17 +1161,18 @@ public final class TextFormat {
* Un-escape a text string as escaped using {@link #escapeText(String)}.
* Two-digit hex escapes (starting with "\x") are also recognized.
*/
- static String unescapeText(String input) throws InvalidEscapeSequence {
+ static String unescapeText(final String input)
+ throws InvalidEscapeSequenceException {
return unescapeBytes(input).toStringUtf8();
}
/** Is this an octal digit? */
- private static boolean isOctal(char c) {
+ private static boolean isOctal(final char c) {
return '0' <= c && c <= '7';
}
/** Is this a hex digit? */
- private static boolean isHex(char c) {
+ private static boolean isHex(final char c) {
return ('0' <= c && c <= '9') ||
('a' <= c && c <= 'f') ||
('A' <= c && c <= 'F');
@@ -1151,7 +1183,7 @@ public final class TextFormat {
* numeric value. This is like {@code Character.digit()} but we don't accept
* non-ASCII digits.
*/
- private static int digitValue(char c) {
+ private static int digitValue(final char c) {
if ('0' <= c && c <= '9') {
return c - '0';
} else if ('a' <= c && c <= 'z') {
@@ -1166,7 +1198,7 @@ public final class TextFormat {
* {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
* and "0" to signify hexidecimal and octal numbers, respectively.
*/
- static int parseInt32(String text) throws NumberFormatException {
+ static int parseInt32(final String text) throws NumberFormatException {
return (int) parseInteger(text, true, false);
}
@@ -1177,7 +1209,7 @@ public final class TextFormat {
* result is coerced to a (signed) {@code int} when returned since Java has
* no unsigned integer type.
*/
- static int parseUInt32(String text) throws NumberFormatException {
+ static int parseUInt32(final String text) throws NumberFormatException {
return (int) parseInteger(text, false, false);
}
@@ -1186,7 +1218,7 @@ public final class TextFormat {
* {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
* and "0" to signify hexidecimal and octal numbers, respectively.
*/
- static long parseInt64(String text) throws NumberFormatException {
+ static long parseInt64(final String text) throws NumberFormatException {
return parseInteger(text, true, true);
}
@@ -1197,13 +1229,13 @@ public final class TextFormat {
* result is coerced to a (signed) {@code long} when returned since Java has
* no unsigned long type.
*/
- static long parseUInt64(String text) throws NumberFormatException {
+ static long parseUInt64(final String text) throws NumberFormatException {
return parseInteger(text, false, true);
}
- private static long parseInteger(String text,
- boolean isSigned,
- boolean isLong)
+ private static long parseInteger(final String text,
+ final boolean isSigned,
+ final boolean isLong)
throws NumberFormatException {
int pos = 0;
@@ -1224,7 +1256,7 @@ public final class TextFormat {
radix = 8;
}
- String numberText = text.substring(pos);
+ final String numberText = text.substring(pos);
long result = 0;
if (numberText.length() < 16) {
diff --git a/java/src/main/java/com/google/protobuf/UninitializedMessageException.java b/java/src/main/java/com/google/protobuf/UninitializedMessageException.java
index a1032caa..8743c120 100644
--- a/java/src/main/java/com/google/protobuf/UninitializedMessageException.java
+++ b/java/src/main/java/com/google/protobuf/UninitializedMessageException.java
@@ -30,12 +30,8 @@
package com.google.protobuf;
-import com.google.protobuf.Descriptors.FieldDescriptor;
-
-import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.Map;
/**
* Thrown when attempting to build a protocol message that is missing required
@@ -51,11 +47,15 @@ import java.util.Map;
* @author kenton@google.com Kenton Varda
*/
public class UninitializedMessageException extends RuntimeException {
- public UninitializedMessageException(Message message) {
- this(findMissingFields(message));
+ private static final long serialVersionUID = -7466929953374883507L;
+
+ public UninitializedMessageException(final MessageLite message) {
+ super("Message was missing required fields. (Lite runtime could not " +
+ "determine which fields were missing).");
+ missingFields = null;
}
- private UninitializedMessageException(List<String> missingFields) {
+ public UninitializedMessageException(final List<String> missingFields) {
super(buildDescription(missingFields));
this.missingFields = missingFields;
}
@@ -65,6 +65,8 @@ public class UninitializedMessageException extends RuntimeException {
/**
* Get a list of human-readable names of required fields missing from this
* message. Each name is a full path to a field, e.g. "foo.bar[5].baz".
+ * Returns null if the lite runtime was used, since it lacks the ability to
+ * find missing fields.
*/
public List<String> getMissingFields() {
return Collections.unmodifiableList(missingFields);
@@ -80,11 +82,11 @@ public class UninitializedMessageException extends RuntimeException {
}
/** Construct the description string for this exception. */
- private static String buildDescription(List<String> missingFields) {
- StringBuilder description =
+ private static String buildDescription(final List<String> missingFields) {
+ final StringBuilder description =
new StringBuilder("Message missing required fields: ");
boolean first = true;
- for (String field : missingFields) {
+ for (final String field : missingFields) {
if (first) {
first = false;
} else {
@@ -94,67 +96,4 @@ public class UninitializedMessageException extends RuntimeException {
}
return description.toString();
}
-
- /**
- * Populates {@code this.missingFields} with the full "path" of each
- * missing required field in the given message.
- */
- private static List<String> findMissingFields(Message message) {
- List<String> results = new ArrayList<String>();
- findMissingFields(message, "", results);
- return results;
- }
-
- /** Recursive helper implementing {@link #findMissingFields(Message)}. */
- private static void findMissingFields(Message message, String prefix,
- List<String> results) {
- for (FieldDescriptor field : message.getDescriptorForType().getFields()) {
- if (field.isRequired() && !message.hasField(field)) {
- results.add(prefix + field.getName());
- }
- }
-
- for (Map.Entry<FieldDescriptor, Object> entry :
- message.getAllFields().entrySet()) {
- FieldDescriptor field = entry.getKey();
- Object value = entry.getValue();
-
- if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
- if (field.isRepeated()) {
- int i = 0;
- for (Object element : (List) value) {
- findMissingFields((Message) element,
- subMessagePrefix(prefix, field, i++),
- results);
- }
- } else {
- if (message.hasField(field)) {
- findMissingFields((Message) value,
- subMessagePrefix(prefix, field, -1),
- results);
- }
- }
- }
- }
- }
-
- private static String subMessagePrefix(String prefix,
- FieldDescriptor field,
- int index) {
- StringBuilder result = new StringBuilder(prefix);
- if (field.isExtension()) {
- result.append('(')
- .append(field.getFullName())
- .append(')');
- } else {
- result.append(field.getName());
- }
- if (index != -1) {
- result.append('[')
- .append(index)
- .append(']');
- }
- result.append('.');
- return result.toString();
- }
}
diff --git a/java/src/main/java/com/google/protobuf/UnknownFieldSet.java b/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
index 77fef323..239c2aca 100644
--- a/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
+++ b/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
@@ -30,15 +30,17 @@
package com.google.protobuf;
-import java.io.InputStream;
+import com.google.protobuf.Internal.ThreadLocalQuickQueue;
+
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.TreeMap;
import java.util.List;
import java.util.Map;
+import java.util.TreeMap;
/**
* {@code UnknownFieldSet} is used to keep track of fields which were seen when
@@ -48,56 +50,59 @@ import java.util.Map;
* compiled before the new types were added.
*
* <p>Every {@link Message} contains an {@code UnknownFieldSet} (and every
- * {@link Message.Builder} contains an {@link UnknownFieldSet.Builder}).
+ * {@link Message.Builder} contains an {@link Builder}).
*
* <p>Most users will never need to use this class.
*
* @author kenton@google.com Kenton Varda
*/
-public final class UnknownFieldSet {
+public final class UnknownFieldSet implements MessageLite {
private UnknownFieldSet() {}
- /** Create a new {@link UnknownFieldSet.Builder}. */
+ /** Create a new {@link Builder}. */
public static Builder newBuilder() {
- return new Builder();
+ return Builder.create();
}
/**
- * Create a new {@link UnknownFieldSet.Builder} and initialize it to be a copy
+ * Create a new {@link Builder} and initialize it to be a copy
* of {@code copyFrom}.
*/
- public static Builder newBuilder(UnknownFieldSet copyFrom) {
- return new Builder().mergeFrom(copyFrom);
+ public static Builder newBuilder(final UnknownFieldSet copyFrom) {
+ return newBuilder().mergeFrom(copyFrom);
}
/** Get an empty {@code UnknownFieldSet}. */
public static UnknownFieldSet getDefaultInstance() {
return defaultInstance;
}
- private static UnknownFieldSet defaultInstance =
+ public UnknownFieldSet getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+ private static final UnknownFieldSet defaultInstance =
new UnknownFieldSet(Collections.<Integer, Field>emptyMap());
/**
* Construct an {@code UnknownFieldSet} around the given map. The map is
* expected to be immutable.
*/
- private UnknownFieldSet(Map<Integer, Field> fields) {
+ private UnknownFieldSet(final Map<Integer, Field> fields) {
this.fields = fields;
}
private Map<Integer, Field> fields;
@Override
- public boolean equals(Object other) {
+ public boolean equals(final Object other) {
if (this == other) {
return true;
}
return (other instanceof UnknownFieldSet) &&
- this.fields.equals(((UnknownFieldSet) other).fields);
+ fields.equals(((UnknownFieldSet) other).fields);
}
@Override
public int hashCode() {
- return this.fields.hashCode();
+ return fields.hashCode();
}
/** Get a map of fields in the set by number. */
@@ -106,7 +111,7 @@ public final class UnknownFieldSet {
}
/** Check if the given field number is present in the set. */
- public boolean hasField(int number) {
+ public boolean hasField(final int number) {
return fields.containsKey(number);
}
@@ -114,14 +119,14 @@ public final class UnknownFieldSet {
* Get a field by number. Returns an empty field if not present. Never
* returns {@code null}.
*/
- public Field getField(int number) {
- Field result = fields.get(number);
+ public Field getField(final int number) {
+ final Field result = fields.get(number);
return (result == null) ? Field.getDefaultInstance() : result;
}
/** Serializes the set and writes it to {@code output}. */
- public void writeTo(CodedOutputStream output) throws IOException {
- for (Map.Entry<Integer, Field> entry : fields.entrySet()) {
+ public void writeTo(final CodedOutputStream output) throws IOException {
+ for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
entry.getValue().writeTo(entry.getKey(), output);
}
}
@@ -131,7 +136,8 @@ public final class UnknownFieldSet {
* just a trivial wrapper around
* {@link TextFormat#printToString(UnknownFieldSet)}.
*/
- public final String toString() {
+ @Override
+ public String toString() {
return TextFormat.printToString(this);
}
@@ -139,13 +145,13 @@ public final class UnknownFieldSet {
* Serializes the message to a {@code ByteString} and returns it. This is
* just a trivial wrapper around {@link #writeTo(CodedOutputStream)}.
*/
- public final ByteString toByteString() {
+ public ByteString toByteString() {
try {
- ByteString.CodedBuilder out =
+ final ByteString.CodedBuilder out =
ByteString.newCodedBuilder(getSerializedSize());
writeTo(out.getCodedOutput());
return out.build();
- } catch (IOException e) {
+ } catch (final IOException e) {
throw new RuntimeException(
"Serializing to a ByteString threw an IOException (should " +
"never happen).", e);
@@ -156,14 +162,14 @@ public final class UnknownFieldSet {
* Serializes the message to a {@code byte} array and returns it. This is
* just a trivial wrapper around {@link #writeTo(CodedOutputStream)}.
*/
- public final byte[] toByteArray() {
+ public byte[] toByteArray() {
try {
- byte[] result = new byte[getSerializedSize()];
- CodedOutputStream output = CodedOutputStream.newInstance(result);
+ final byte[] result = new byte[getSerializedSize()];
+ final CodedOutputStream output = CodedOutputStream.newInstance(result);
writeTo(output);
output.checkNoSpaceLeft();
return result;
- } catch (IOException e) {
+ } catch (final IOException e) {
throw new RuntimeException(
"Serializing to a byte array threw an IOException " +
"(should never happen).", e);
@@ -174,8 +180,15 @@ public final class UnknownFieldSet {
* Serializes the message and writes it to {@code output}. This is just a
* trivial wrapper around {@link #writeTo(CodedOutputStream)}.
*/
- public final void writeTo(OutputStream output) throws IOException {
- CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
+ public void writeTo(final OutputStream output) throws IOException {
+ final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
+ writeTo(codedOutput);
+ codedOutput.flush();
+ }
+
+ public void writeDelimitedTo(OutputStream output) throws IOException {
+ final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
+ codedOutput.writeRawVarint32(getSerializedSize());
writeTo(codedOutput);
codedOutput.flush();
}
@@ -183,7 +196,7 @@ public final class UnknownFieldSet {
/** Get the number of bytes required to encode this set. */
public int getSerializedSize() {
int result = 0;
- for (Map.Entry<Integer, Field> entry : fields.entrySet()) {
+ for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
result += entry.getValue().getSerializedSize(entry.getKey());
}
return result;
@@ -193,9 +206,9 @@ public final class UnknownFieldSet {
* Serializes the set and writes it to {@code output} using
* {@code MessageSet} wire format.
*/
- public void writeAsMessageSetTo(CodedOutputStream output)
+ public void writeAsMessageSetTo(final CodedOutputStream output)
throws IOException {
- for (Map.Entry<Integer, Field> entry : fields.entrySet()) {
+ for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
entry.getValue().writeAsMessageSetExtensionTo(
entry.getKey(), output);
}
@@ -207,37 +220,51 @@ public final class UnknownFieldSet {
*/
public int getSerializedSizeAsMessageSet() {
int result = 0;
- for (Map.Entry<Integer, Field> entry : fields.entrySet()) {
+ for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
result += entry.getValue().getSerializedSizeAsMessageSetExtension(
entry.getKey());
}
return result;
}
+ public boolean isInitialized() {
+ // UnknownFieldSets do not have required fields, so they are always
+ // initialized.
+ return true;
+ }
+
/** Parse an {@code UnknownFieldSet} from the given input stream. */
- static public UnknownFieldSet parseFrom(CodedInputStream input)
+ public static UnknownFieldSet parseFrom(final CodedInputStream input)
throws IOException {
return newBuilder().mergeFrom(input).build();
}
/** Parse {@code data} as an {@code UnknownFieldSet} and return it. */
- public static UnknownFieldSet parseFrom(ByteString data)
+ public static UnknownFieldSet parseFrom(final ByteString data)
throws InvalidProtocolBufferException {
return newBuilder().mergeFrom(data).build();
}
/** Parse {@code data} as an {@code UnknownFieldSet} and return it. */
- public static UnknownFieldSet parseFrom(byte[] data)
+ public static UnknownFieldSet parseFrom(final byte[] data)
throws InvalidProtocolBufferException {
return newBuilder().mergeFrom(data).build();
}
/** Parse an {@code UnknownFieldSet} from {@code input} and return it. */
- public static UnknownFieldSet parseFrom(InputStream input)
+ public static UnknownFieldSet parseFrom(final InputStream input)
throws IOException {
return newBuilder().mergeFrom(input).build();
}
+ public Builder newBuilderForType() {
+ return newBuilder();
+ }
+
+ public Builder toBuilder() {
+ return newBuilder().mergeFrom(this);
+ }
+
/**
* Builder for {@link UnknownFieldSet}s.
*
@@ -250,21 +277,35 @@ public final class UnknownFieldSet {
*
* <p>Use {@link UnknownFieldSet#newBuilder()} to construct a {@code Builder}.
*/
- public static final class Builder {
+ public static final class Builder implements MessageLite.Builder {
+ private static ThreadLocalQuickQueue<Builder> builders =
+ new ThreadLocalQuickQueue<Builder>();
+
+ // This constructor should never be called directly (except from 'create').
private Builder() {}
- private Map<Integer, Field> fields = new TreeMap<Integer, Field>();
+
+ private Map<Integer, Field> fields;
// Optimization: We keep around a builder for the last field that was
// modified so that we can efficiently add to it multiple times in a
// row (important when parsing an unknown repeated field).
- int lastFieldNumber = 0;
- Field.Builder lastField = null;
+ private int lastFieldNumber;
+ private Field.Builder lastField;
+
+ private static Builder create() {
+ Builder builder = builders.get().poll();
+ if (builder == null) {
+ builder = new Builder();
+ }
+ builder.reinitialize();
+ return builder;
+ }
/**
* Get a field builder for the given field number which includes any
* values that already exist.
*/
- private Field.Builder getFieldBuilder(int number) {
+ private Field.Builder getFieldBuilder(final int number) {
if (lastField != null) {
if (number == lastFieldNumber) {
return lastField;
@@ -275,7 +316,7 @@ public final class UnknownFieldSet {
if (number == 0) {
return null;
} else {
- Field existing = fields.get(number);
+ final Field existing = fields.get(number);
lastFieldNumber = number;
lastField = Field.newBuilder();
if (existing != null) {
@@ -289,26 +330,48 @@ public final class UnknownFieldSet {
* Build the {@link UnknownFieldSet} and return it.
*
* <p>Once {@code build()} has been called, the {@code Builder} will no
- * longer be usable. Calling any method after {@code build()} will throw
- * {@code NullPointerException}.
+ * longer be usable. Calling any method after {@code build()} will result
+ * in undefined behavior and can cause a {@code NullPointerException} to be
+ * thrown.
*/
public UnknownFieldSet build() {
getFieldBuilder(0); // Force lastField to be built.
- UnknownFieldSet result;
+ final UnknownFieldSet result;
if (fields.isEmpty()) {
result = getDefaultInstance();
} else {
result = new UnknownFieldSet(Collections.unmodifiableMap(fields));
}
fields = null;
+ builders.get().offer(this);
return result;
}
- /** Reset the builder to an empty set. */
- public Builder clear() {
- fields = new TreeMap<Integer, Field>();
+ public UnknownFieldSet buildPartial() {
+ // No required fields, so this is the same as build().
+ return build();
+ }
+
+ @Override
+ public Builder clone() {
+ getFieldBuilder(0); // Force lastField to be built.
+ return UnknownFieldSet.newBuilder().mergeFrom(
+ new UnknownFieldSet(fields));
+ }
+
+ public UnknownFieldSet getDefaultInstanceForType() {
+ return UnknownFieldSet.getDefaultInstance();
+ }
+
+ private void reinitialize() {
+ fields = Collections.emptyMap();
lastFieldNumber = 0;
lastField = null;
+ }
+
+ /** Reset the builder to an empty set. */
+ public Builder clear() {
+ reinitialize();
return this;
}
@@ -317,9 +380,9 @@ public final class UnknownFieldSet {
* exists in both sets, {@code other}'s values for that field will be
* appended to the values in this set.
*/
- public Builder mergeFrom(UnknownFieldSet other) {
+ public Builder mergeFrom(final UnknownFieldSet other) {
if (other != getDefaultInstance()) {
- for (Map.Entry<Integer, Field> entry : other.fields.entrySet()) {
+ for (final Map.Entry<Integer, Field> entry : other.fields.entrySet()) {
mergeField(entry.getKey(), entry.getValue());
}
}
@@ -330,7 +393,7 @@ public final class UnknownFieldSet {
* Add a field to the {@code UnknownFieldSet}. If a field with the same
* number already exists, the two are merged.
*/
- public Builder mergeField(int number, Field field) {
+ public Builder mergeField(final int number, final Field field) {
if (number == 0) {
throw new IllegalArgumentException("Zero is not a valid field number.");
}
@@ -350,7 +413,7 @@ public final class UnknownFieldSet {
* value. This is used in particular when an unknown enum value is
* encountered.
*/
- public Builder mergeVarintField(int number, int value) {
+ public Builder mergeVarintField(final int number, final int value) {
if (number == 0) {
throw new IllegalArgumentException("Zero is not a valid field number.");
}
@@ -359,7 +422,7 @@ public final class UnknownFieldSet {
}
/** Check if the given field number is present in the set. */
- public boolean hasField(int number) {
+ public boolean hasField(final int number) {
if (number == 0) {
throw new IllegalArgumentException("Zero is not a valid field number.");
}
@@ -370,7 +433,7 @@ public final class UnknownFieldSet {
* Add a field to the {@code UnknownFieldSet}. If a field with the same
* number already exists, it is removed.
*/
- public Builder addField(int number, Field field) {
+ public Builder addField(final int number, final Field field) {
if (number == 0) {
throw new IllegalArgumentException("Zero is not a valid field number.");
}
@@ -379,6 +442,9 @@ public final class UnknownFieldSet {
lastField = null;
lastFieldNumber = 0;
}
+ if (fields.isEmpty()) {
+ fields = new TreeMap<Integer,Field>();
+ }
fields.put(number, field);
return this;
}
@@ -396,9 +462,9 @@ public final class UnknownFieldSet {
* Parse an entire message from {@code input} and merge its fields into
* this set.
*/
- public Builder mergeFrom(CodedInputStream input) throws IOException {
+ public Builder mergeFrom(final CodedInputStream input) throws IOException {
while (true) {
- int tag = input.readTag();
+ final int tag = input.readTag();
if (tag == 0 || !mergeFieldFrom(tag, input)) {
break;
}
@@ -411,9 +477,9 @@ public final class UnknownFieldSet {
* @param tag The field's tag number, which was already parsed.
* @return {@code false} if the tag is an engroup tag.
*/
- public boolean mergeFieldFrom(int tag, CodedInputStream input)
+ public boolean mergeFieldFrom(final int tag, final CodedInputStream input)
throws IOException {
- int number = WireFormat.getTagFieldNumber(tag);
+ final int number = WireFormat.getTagFieldNumber(tag);
switch (WireFormat.getTagWireType(tag)) {
case WireFormat.WIRETYPE_VARINT:
getFieldBuilder(number).addVarint(input.readInt64());
@@ -424,12 +490,12 @@ public final class UnknownFieldSet {
case WireFormat.WIRETYPE_LENGTH_DELIMITED:
getFieldBuilder(number).addLengthDelimited(input.readBytes());
return true;
- case WireFormat.WIRETYPE_START_GROUP: {
- UnknownFieldSet.Builder subBuilder = UnknownFieldSet.newBuilder();
- input.readUnknownGroup(number, subBuilder);
+ case WireFormat.WIRETYPE_START_GROUP:
+ final Builder subBuilder = newBuilder();
+ input.readGroup(number, subBuilder,
+ ExtensionRegistry.getEmptyRegistry());
getFieldBuilder(number).addGroup(subBuilder.build());
return true;
- }
case WireFormat.WIRETYPE_END_GROUP:
return false;
case WireFormat.WIRETYPE_FIXED32:
@@ -445,16 +511,16 @@ public final class UnknownFieldSet {
* set being built. This is just a small wrapper around
* {@link #mergeFrom(CodedInputStream)}.
*/
- public Builder mergeFrom(ByteString data)
+ public Builder mergeFrom(final ByteString data)
throws InvalidProtocolBufferException {
try {
- CodedInputStream input = data.newCodedInput();
+ final CodedInputStream input = data.newCodedInput();
mergeFrom(input);
input.checkLastTagWas(0);
return this;
- } catch (InvalidProtocolBufferException e) {
+ } catch (final InvalidProtocolBufferException e) {
throw e;
- } catch (IOException e) {
+ } catch (final IOException e) {
throw new RuntimeException(
"Reading from a ByteString threw an IOException (should " +
"never happen).", e);
@@ -466,16 +532,16 @@ public final class UnknownFieldSet {
* set being built. This is just a small wrapper around
* {@link #mergeFrom(CodedInputStream)}.
*/
- public Builder mergeFrom(byte[] data)
+ public Builder mergeFrom(final byte[] data)
throws InvalidProtocolBufferException {
try {
- CodedInputStream input = CodedInputStream.newInstance(data);
+ final CodedInputStream input = CodedInputStream.newInstance(data);
mergeFrom(input);
input.checkLastTagWas(0);
return this;
- } catch (InvalidProtocolBufferException e) {
+ } catch (final InvalidProtocolBufferException e) {
throw e;
- } catch (IOException e) {
+ } catch (final IOException e) {
throw new RuntimeException(
"Reading from a byte array threw an IOException (should " +
"never happen).", e);
@@ -487,12 +553,88 @@ public final class UnknownFieldSet {
* set being built. This is just a small wrapper around
* {@link #mergeFrom(CodedInputStream)}.
*/
- public Builder mergeFrom(InputStream input) throws IOException {
- CodedInputStream codedInput = CodedInputStream.newInstance(input);
+ public Builder mergeFrom(final InputStream input) throws IOException {
+ final CodedInputStream codedInput = CodedInputStream.newInstance(input);
mergeFrom(codedInput);
codedInput.checkLastTagWas(0);
return this;
}
+
+ public Builder mergeDelimitedFrom(InputStream input)
+ throws IOException {
+ final int size = CodedInputStream.readRawVarint32(input);
+ final InputStream limitedInput =
+ new AbstractMessage.Builder.LimitedInputStream(input, size);
+ return mergeFrom(limitedInput, null);
+ }
+
+ public Builder mergeDelimitedFrom(
+ InputStream input,
+ ExtensionRegistryLite extensionRegistry) throws IOException {
+ // UnknownFieldSet has no extensions.
+ return mergeFrom(input);
+ }
+
+ public Builder mergeFrom(
+ CodedInputStream input,
+ ExtensionRegistryLite extensionRegistry) throws IOException {
+ // UnknownFieldSet has no extensions.
+ return mergeFrom(input);
+ }
+
+ 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 {
+ try {
+ final CodedInputStream input =
+ CodedInputStream.newInstance(data, off, len);
+ mergeFrom(input);
+ input.checkLastTagWas(0);
+ return this;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new RuntimeException(
+ "Reading from a byte array threw an IOException (should " +
+ "never happen).", e);
+ }
+ }
+
+ 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)
+ throws InvalidProtocolBufferException {
+ // UnknownFieldSet has no extensions.
+ return mergeFrom(data, off, len);
+ }
+
+ public Builder mergeFrom(
+ InputStream input,
+ ExtensionRegistryLite extensionRegistry) throws IOException {
+ // UnknownFieldSet has no extensions.
+ return mergeFrom(input);
+ }
+
+ public boolean isInitialized() {
+ // UnknownFieldSets do not have required fields, so they are always
+ // initialized.
+ return true;
+ }
}
/**
@@ -510,7 +652,7 @@ public final class UnknownFieldSet {
* wire types.
*
* <p>{@code Field} is an immutable class. To construct one, you must use a
- * {@link Field.Builder}.
+ * {@link Builder}.
*
* @see UnknownFieldSet
*/
@@ -519,22 +661,22 @@ public final class UnknownFieldSet {
/** Construct a new {@link Builder}. */
public static Builder newBuilder() {
- return new Builder();
+ return Builder.create();
}
/**
* Construct a new {@link Builder} and initialize it to a copy of
* {@code copyFrom}.
*/
- public static Builder newBuilder(Field copyFrom) {
- return new Builder().mergeFrom(copyFrom);
+ public static Builder newBuilder(final Field copyFrom) {
+ return newBuilder().mergeFrom(copyFrom);
}
/** Get an empty {@code Field}. */
public static Field getDefaultInstance() {
- return defaultInstance;
+ return fieldDefaultInstance;
}
- private static Field defaultInstance = newBuilder().build();
+ private static final Field fieldDefaultInstance = newBuilder().build();
/** Get the list of varint values for this field. */
public List<Long> getVarintList() { return varint; }
@@ -556,14 +698,14 @@ public final class UnknownFieldSet {
public List<UnknownFieldSet> getGroupList() { return group; }
@Override
- public boolean equals(Object other) {
+ public boolean equals(final Object other) {
if (this == other) {
return true;
}
if (!(other instanceof Field)) {
return false;
}
- return Arrays.equals(this.getIdentityArray(),
+ return Arrays.equals(getIdentityArray(),
((Field) other).getIdentityArray());
}
@@ -574,37 +716,37 @@ public final class UnknownFieldSet {
/**
* Returns the array of objects to be used to uniquely identify this
- * {@link UnknownFieldSet.Field} instance.
+ * {@link Field} instance.
*/
private Object[] getIdentityArray() {
return new Object[] {
- this.varint,
- this.fixed32,
- this.fixed64,
- this.lengthDelimited,
- this.group};
+ varint,
+ fixed32,
+ fixed64,
+ lengthDelimited,
+ group};
}
/**
* Serializes the field, including field number, and writes it to
* {@code output}.
*/
- public void writeTo(int fieldNumber, CodedOutputStream output)
+ public void writeTo(final int fieldNumber, final CodedOutputStream output)
throws IOException {
- for (long value : varint) {
+ for (final long value : varint) {
output.writeUInt64(fieldNumber, value);
}
- for (int value : fixed32) {
+ for (final int value : fixed32) {
output.writeFixed32(fieldNumber, value);
}
- for (long value : fixed64) {
+ for (final long value : fixed64) {
output.writeFixed64(fieldNumber, value);
}
- for (ByteString value : lengthDelimited) {
+ for (final ByteString value : lengthDelimited) {
output.writeBytes(fieldNumber, value);
}
- for (UnknownFieldSet value : group) {
- output.writeUnknownGroup(fieldNumber, value);
+ for (final UnknownFieldSet value : group) {
+ output.writeGroup(fieldNumber, value);
}
}
@@ -612,22 +754,22 @@ public final class UnknownFieldSet {
* Get the number of bytes required to encode this field, including field
* number.
*/
- public int getSerializedSize(int fieldNumber) {
+ public int getSerializedSize(final int fieldNumber) {
int result = 0;
- for (long value : varint) {
+ for (final long value : varint) {
result += CodedOutputStream.computeUInt64Size(fieldNumber, value);
}
- for (int value : fixed32) {
+ for (final int value : fixed32) {
result += CodedOutputStream.computeFixed32Size(fieldNumber, value);
}
- for (long value : fixed64) {
+ for (final long value : fixed64) {
result += CodedOutputStream.computeFixed64Size(fieldNumber, value);
}
- for (ByteString value : lengthDelimited) {
+ for (final ByteString value : lengthDelimited) {
result += CodedOutputStream.computeBytesSize(fieldNumber, value);
}
- for (UnknownFieldSet value : group) {
- result += CodedOutputStream.computeUnknownGroupSize(fieldNumber, value);
+ for (final UnknownFieldSet value : group) {
+ result += CodedOutputStream.computeGroupSize(fieldNumber, value);
}
return result;
}
@@ -637,10 +779,10 @@ public final class UnknownFieldSet {
* {@code output}, using {@code MessageSet} wire format.
*/
public void writeAsMessageSetExtensionTo(
- int fieldNumber,
- CodedOutputStream output)
+ final int fieldNumber,
+ final CodedOutputStream output)
throws IOException {
- for (ByteString value : lengthDelimited) {
+ for (final ByteString value : lengthDelimited) {
output.writeRawMessageSetExtension(fieldNumber, value);
}
}
@@ -649,9 +791,9 @@ public final class UnknownFieldSet {
* Get the number of bytes required to encode this field, including field
* number, using {@code MessageSet} wire format.
*/
- public int getSerializedSizeAsMessageSetExtension(int fieldNumber) {
+ public int getSerializedSizeAsMessageSetExtension(final int fieldNumber) {
int result = 0;
- for (ByteString value : lengthDelimited) {
+ for (final ByteString value : lengthDelimited) {
result += CodedOutputStream.computeRawMessageSetExtensionSize(
fieldNumber, value);
}
@@ -670,13 +812,29 @@ public final class UnknownFieldSet {
* <p>Use {@link Field#newBuilder()} to construct a {@code Builder}.
*/
public static final class Builder {
+ private static ThreadLocalQuickQueue<Builder> builders =
+ new ThreadLocalQuickQueue<Builder>();
+
+ // This constructor should never be called directly (except from 'create').
private Builder() {}
- private Field result = new Field();
+
+ private static Builder create() {
+ Builder builder = builders.get().poll();
+ if (builder == null) {
+ builder = new Builder();
+ }
+
+ builder.result = new Field();
+ return builder;
+ }
+
+ private Field result;
/**
* Build the field. After {@code build()} has been called, the
* {@code Builder} is no longer usable. Calling any other method will
- * throw a {@code NullPointerException}.
+ * result in undefined behavior and can cause a
+ * {@code NullPointerException} to be thrown.
*/
public Field build() {
if (result.varint == null) {
@@ -706,8 +864,9 @@ public final class UnknownFieldSet {
result.group = Collections.unmodifiableList(result.group);
}
- Field returnMe = result;
+ final Field returnMe = result;
result = null;
+ builders.get().offer(this);
return returnMe;
}
@@ -722,7 +881,7 @@ public final class UnknownFieldSet {
* of values, {@code other}'s values are append to the ones in this
* field.
*/
- public Builder mergeFrom(Field other) {
+ public Builder mergeFrom(final Field other) {
if (!other.varint.isEmpty()) {
if (result.varint == null) {
result.varint = new ArrayList<Long>();
@@ -757,7 +916,7 @@ public final class UnknownFieldSet {
}
/** Add a varint value. */
- public Builder addVarint(long value) {
+ public Builder addVarint(final long value) {
if (result.varint == null) {
result.varint = new ArrayList<Long>();
}
@@ -766,7 +925,7 @@ public final class UnknownFieldSet {
}
/** Add a fixed32 value. */
- public Builder addFixed32(int value) {
+ public Builder addFixed32(final int value) {
if (result.fixed32 == null) {
result.fixed32 = new ArrayList<Integer>();
}
@@ -775,7 +934,7 @@ public final class UnknownFieldSet {
}
/** Add a fixed64 value. */
- public Builder addFixed64(long value) {
+ public Builder addFixed64(final long value) {
if (result.fixed64 == null) {
result.fixed64 = new ArrayList<Long>();
}
@@ -784,7 +943,7 @@ public final class UnknownFieldSet {
}
/** Add a length-delimited value. */
- public Builder addLengthDelimited(ByteString value) {
+ public Builder addLengthDelimited(final ByteString value) {
if (result.lengthDelimited == null) {
result.lengthDelimited = new ArrayList<ByteString>();
}
@@ -793,7 +952,7 @@ public final class UnknownFieldSet {
}
/** Add an embedded group. */
- public Builder addGroup(UnknownFieldSet value) {
+ public Builder addGroup(final UnknownFieldSet value) {
if (result.group == null) {
result.group = new ArrayList<UnknownFieldSet>();
}
diff --git a/java/src/main/java/com/google/protobuf/WireFormat.java b/java/src/main/java/com/google/protobuf/WireFormat.java
index 2faf2448..3b0bdcd0 100644
--- a/java/src/main/java/com/google/protobuf/WireFormat.java
+++ b/java/src/main/java/com/google/protobuf/WireFormat.java
@@ -56,54 +56,84 @@ public final class WireFormat {
static final int TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1;
/** Given a tag value, determines the wire type (the lower 3 bits). */
- static int getTagWireType(int tag) {
+ static int getTagWireType(final int tag) {
return tag & TAG_TYPE_MASK;
}
/** Given a tag value, determines the field number (the upper 29 bits). */
- public static int getTagFieldNumber(int tag) {
+ public static int getTagFieldNumber(final int tag) {
return tag >>> TAG_TYPE_BITS;
}
/** Makes a tag value given a field number and wire type. */
- static int makeTag(int fieldNumber, int wireType) {
+ static int makeTag(final int fieldNumber, final int wireType) {
return (fieldNumber << TAG_TYPE_BITS) | wireType;
}
- static int getWireFormatForFieldType(Descriptors.FieldDescriptor.Type type) {
- switch (type) {
- case DOUBLE : return WIRETYPE_FIXED64;
- case FLOAT : return WIRETYPE_FIXED32;
- case INT64 : return WIRETYPE_VARINT;
- case UINT64 : return WIRETYPE_VARINT;
- case INT32 : return WIRETYPE_VARINT;
- case FIXED64 : return WIRETYPE_FIXED64;
- case FIXED32 : return WIRETYPE_FIXED32;
- case BOOL : return WIRETYPE_VARINT;
- case STRING : return WIRETYPE_LENGTH_DELIMITED;
- case GROUP : return WIRETYPE_START_GROUP;
- case MESSAGE : return WIRETYPE_LENGTH_DELIMITED;
- case BYTES : return WIRETYPE_LENGTH_DELIMITED;
- case UINT32 : return WIRETYPE_VARINT;
- case ENUM : return WIRETYPE_VARINT;
- case SFIXED32: return WIRETYPE_FIXED32;
- case SFIXED64: return WIRETYPE_FIXED64;
- case SINT32 : return WIRETYPE_VARINT;
- case SINT64 : return WIRETYPE_VARINT;
+ /**
+ * Lite equivalent to {@link Descriptors.FieldDescriptor.JavaType}. This is
+ * only here to support the lite runtime and should not be used by users.
+ */
+ public enum JavaType {
+ INT(0),
+ LONG(0L),
+ FLOAT(0F),
+ DOUBLE(0D),
+ BOOLEAN(false),
+ STRING(""),
+ BYTE_STRING(ByteString.EMPTY),
+ ENUM(null),
+ MESSAGE(null);
+
+ JavaType(final Object defaultDefault) {
+ this.defaultDefault = defaultDefault;
+ }
+
+ /**
+ * The default default value for fields of this type, if it's a primitive
+ * type.
+ */
+ Object getDefaultDefault() {
+ return defaultDefault;
}
- throw new RuntimeException(
- "There is no way to get here, but the compiler thinks otherwise.");
+ private final Object defaultDefault;
}
- /** Given a field descriptor, returns the wire type. This differs from
- * getWireFormatForFieldType for packed repeated fields. */
- static int getWireFormatForField(Descriptors.FieldDescriptor descriptor) {
- if (descriptor.getOptions().getPacked()) {
- return WIRETYPE_LENGTH_DELIMITED;
- } else {
- return getWireFormatForFieldType(descriptor.getType());
+ /**
+ * Lite equivalent to {@link Descriptors.FieldDescriptor.Type}. This is
+ * only here to support the lite runtime and should not be used by users.
+ */
+ public enum FieldType {
+ DOUBLE (JavaType.DOUBLE , WIRETYPE_FIXED64 ),
+ FLOAT (JavaType.FLOAT , WIRETYPE_FIXED32 ),
+ INT64 (JavaType.LONG , WIRETYPE_VARINT ),
+ UINT64 (JavaType.LONG , WIRETYPE_VARINT ),
+ INT32 (JavaType.INT , WIRETYPE_VARINT ),
+ FIXED64 (JavaType.LONG , WIRETYPE_FIXED64 ),
+ FIXED32 (JavaType.INT , WIRETYPE_FIXED32 ),
+ BOOL (JavaType.BOOLEAN , WIRETYPE_VARINT ),
+ STRING (JavaType.STRING , WIRETYPE_LENGTH_DELIMITED),
+ GROUP (JavaType.MESSAGE , WIRETYPE_START_GROUP ),
+ MESSAGE (JavaType.MESSAGE , WIRETYPE_LENGTH_DELIMITED),
+ BYTES (JavaType.BYTE_STRING, WIRETYPE_LENGTH_DELIMITED),
+ UINT32 (JavaType.INT , WIRETYPE_VARINT ),
+ ENUM (JavaType.ENUM , WIRETYPE_VARINT ),
+ SFIXED32(JavaType.INT , WIRETYPE_FIXED32 ),
+ SFIXED64(JavaType.LONG , WIRETYPE_FIXED64 ),
+ SINT32 (JavaType.INT , WIRETYPE_VARINT ),
+ SINT64 (JavaType.LONG , WIRETYPE_VARINT );
+
+ FieldType(final JavaType javaType, final int wireType) {
+ this.javaType = javaType;
+ this.wireType = wireType;
}
+
+ private final JavaType javaType;
+ private final int wireType;
+
+ public JavaType getJavaType() { return javaType; }
+ public int getWireType() { return wireType; }
}
// Field numbers for feilds in MessageSet wire format.
diff --git a/java/src/test/java/com/google/protobuf/DescriptorsTest.java b/java/src/test/java/com/google/protobuf/DescriptorsTest.java
index 84a75977..6fa56267 100644
--- a/java/src/test/java/com/google/protobuf/DescriptorsTest.java
+++ b/java/src/test/java/com/google/protobuf/DescriptorsTest.java
@@ -367,4 +367,34 @@ public class DescriptorsTest extends TestCase {
assertEquals(UnittestCustomOptions.MethodOpt1.METHODOPT1_VAL2,
method.getOptions().getExtension(UnittestCustomOptions.methodOpt1));
}
+
+ /**
+ * Test that the FieldDescriptor.Type enum is the same as the
+ * WireFormat.FieldType enum.
+ */
+ public void testFieldTypeTablesMatch() throws Exception {
+ FieldDescriptor.Type[] values1 = FieldDescriptor.Type.values();
+ WireFormat.FieldType[] values2 = WireFormat.FieldType.values();
+
+ assertEquals(values1.length, values2.length);
+
+ for (int i = 0; i < values1.length; i++) {
+ assertEquals(values1[i].toString(), values2[i].toString());
+ }
+ }
+
+ /**
+ * Test that the FieldDescriptor.JavaType enum is the same as the
+ * WireFormat.JavaType enum.
+ */
+ public void testJavaTypeTablesMatch() throws Exception {
+ FieldDescriptor.JavaType[] values1 = FieldDescriptor.JavaType.values();
+ WireFormat.JavaType[] values2 = WireFormat.JavaType.values();
+
+ assertEquals(values1.length, values2.length);
+
+ for (int i = 0; i < values1.length; i++) {
+ assertEquals(values1[i].toString(), values2[i].toString());
+ }
+ }
}
diff --git a/java/src/test/java/com/google/protobuf/DynamicMessageTest.java b/java/src/test/java/com/google/protobuf/DynamicMessageTest.java
index 120b0f13..aabccda2 100644
--- a/java/src/test/java/com/google/protobuf/DynamicMessageTest.java
+++ b/java/src/test/java/com/google/protobuf/DynamicMessageTest.java
@@ -73,6 +73,18 @@ public class DynamicMessageTest extends TestCase {
}
}
+ public void testClearAfterBuildError() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ builder.build();
+ try {
+ builder.clear();
+ fail("Should have thrown exception.");
+ } catch (IllegalStateException e) {
+ // Success.
+ }
+ }
+
public void testDynamicMessageSettersRejectNull() throws Exception {
Message.Builder builder =
DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
diff --git a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
index 58d82193..cdf60c5e 100644
--- a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
+++ b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -43,6 +43,8 @@ import protobuf_unittest.MultipleFilesTestProto;
import protobuf_unittest.MessageWithNoOuter;
import protobuf_unittest.EnumWithNoOuter;
import protobuf_unittest.ServiceWithNoOuter;
+import com.google.protobuf.UnittestLite;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
import junit.framework.TestCase;
import java.util.Arrays;
@@ -82,6 +84,17 @@ public class GeneratedMessageTest extends TestCase {
}
}
+ public void testClearAfterBuildError() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.build();
+ try {
+ builder.clear();
+ fail("Should have thrown exception.");
+ } catch (IllegalStateException e) {
+ // Success.
+ }
+ }
+
public void testSettersRejectNull() throws Exception {
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
try {
@@ -338,6 +351,16 @@ public class GeneratedMessageTest extends TestCase {
instanceof ProtocolMessageEnum);
}
+ public void testEnumMap() throws Exception {
+ Internal.EnumLiteMap<ForeignEnum> map = ForeignEnum.internalGetValueMap();
+
+ for (ForeignEnum value : ForeignEnum.values()) {
+ assertEquals(value, map.findValueByNumber(value.getNumber()));
+ }
+
+ assertTrue(map.findValueByNumber(12345) == null);
+ }
+
// =================================================================
// Extensions.
@@ -420,6 +443,12 @@ public class GeneratedMessageTest extends TestCase {
.getExtensionCount(UnittestProto.repeatedInt32Extension));
}
+ public void testExtensionCopy() throws Exception {
+ TestAllExtensions original = TestUtil.getAllExtensionsSet();
+ TestAllExtensions copy = TestAllExtensions.newBuilder(original).build();
+ TestUtil.assertAllExtensionsSet(copy);
+ }
+
public void testExtensionMergeFrom() throws Exception {
TestAllExtensions original =
TestAllExtensions.newBuilder()
@@ -432,6 +461,66 @@ public class GeneratedMessageTest extends TestCase {
}
// =================================================================
+ // Lite Extensions.
+
+ // We test lite extensions directly because they have a separate
+ // implementation from full extensions. In contrast, we do not test
+ // lite fields directly since they are implemented exactly the same as
+ // regular fields.
+
+ public void testLiteExtensionAccessors() throws Exception {
+ TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder();
+ TestUtil.setAllExtensions(builder);
+ TestAllExtensionsLite message = builder.build();
+ TestUtil.assertAllExtensionsSet(message);
+ }
+
+ public void testLiteExtensionRepeatedSetters() throws Exception {
+ TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder();
+ TestUtil.setAllExtensions(builder);
+ TestUtil.modifyRepeatedExtensions(builder);
+ TestAllExtensionsLite message = builder.build();
+ TestUtil.assertRepeatedExtensionsModified(message);
+ }
+
+ public void testLiteExtensionDefaults() throws Exception {
+ TestUtil.assertExtensionsClear(TestAllExtensionsLite.getDefaultInstance());
+ TestUtil.assertExtensionsClear(TestAllExtensionsLite.newBuilder().build());
+ }
+
+ public void testClearLiteExtension() throws Exception {
+ // clearExtension() is not actually used in TestUtil, so try it manually.
+ assertFalse(
+ TestAllExtensionsLite.newBuilder()
+ .setExtension(UnittestLite.optionalInt32ExtensionLite, 1)
+ .clearExtension(UnittestLite.optionalInt32ExtensionLite)
+ .hasExtension(UnittestLite.optionalInt32ExtensionLite));
+ assertEquals(0,
+ TestAllExtensionsLite.newBuilder()
+ .addExtension(UnittestLite.repeatedInt32ExtensionLite, 1)
+ .clearExtension(UnittestLite.repeatedInt32ExtensionLite)
+ .getExtensionCount(UnittestLite.repeatedInt32ExtensionLite));
+ }
+
+ public void testLiteExtensionCopy() throws Exception {
+ TestAllExtensionsLite original = TestUtil.getAllLiteExtensionsSet();
+ TestAllExtensionsLite copy =
+ TestAllExtensionsLite.newBuilder(original).build();
+ TestUtil.assertAllExtensionsSet(copy);
+ }
+
+ public void testLiteExtensionMergeFrom() throws Exception {
+ TestAllExtensionsLite original =
+ TestAllExtensionsLite.newBuilder()
+ .setExtension(UnittestLite.optionalInt32ExtensionLite, 1).build();
+ TestAllExtensionsLite merged =
+ TestAllExtensionsLite.newBuilder().mergeFrom(original).build();
+ assertTrue(merged.hasExtension(UnittestLite.optionalInt32ExtensionLite));
+ assertEquals(
+ 1, (int) merged.getExtension(UnittestLite.optionalInt32ExtensionLite));
+ }
+
+ // =================================================================
// multiple_files_test
public void testMultipleFilesOption() throws Exception {
diff --git a/java/src/test/java/com/google/protobuf/LiteTest.java b/java/src/test/java/com/google/protobuf/LiteTest.java
new file mode 100644
index 00000000..9dd730c2
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/LiteTest.java
@@ -0,0 +1,114 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import com.google.protobuf.UnittestLite;
+import com.google.protobuf.UnittestLite.TestAllTypesLite;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.UnittestLite.TestNestedExtensionLite;
+
+import junit.framework.TestCase;
+
+/**
+ * Test lite runtime.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class LiteTest extends TestCase {
+ public void setUp() throws Exception {
+ // Test that nested extensions are initialized correctly even if the outer
+ // class has not been accessed directly. This was once a bug with lite
+ // messages.
+ //
+ // We put this in setUp() rather than in its own test method because we
+ // need to make sure it runs before any actual tests.
+ assertTrue(TestNestedExtensionLite.nestedExtension != null);
+ }
+
+ public void testLite() throws Exception {
+ // Since lite messages are a subset of regular messages, we can mostly
+ // assume that the functionality of lite messages is already thoroughly
+ // tested by the regular tests. All this test really verifies is that
+ // a proto with optimize_for = LITE_RUNTIME compiles correctly when
+ // linked only against the lite library. That is all tested at compile
+ // time, leaving not much to do in this method. Let's just do some random
+ // stuff to make sure the lite message is actually here and usable.
+
+ TestAllTypesLite message =
+ TestAllTypesLite.newBuilder()
+ .setOptionalInt32(123)
+ .addRepeatedString("hello")
+ .setOptionalNestedMessage(
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(7))
+ .build();
+
+ ByteString data = message.toByteString();
+
+ TestAllTypesLite message2 = TestAllTypesLite.parseFrom(data);
+
+ assertEquals(123, message2.getOptionalInt32());
+ assertEquals(1, message2.getRepeatedStringCount());
+ assertEquals("hello", message2.getRepeatedString(0));
+ assertEquals(7, message2.getOptionalNestedMessage().getBb());
+ }
+
+ public void testLiteExtensions() throws Exception {
+ // TODO(kenton): Unlike other features of the lite library, extensions are
+ // implemented completely differently from the regular library. We
+ // need to test them more thoroughly, once they are fully-implemented.
+
+ TestAllExtensionsLite message =
+ TestAllExtensionsLite.newBuilder()
+ .setExtension(UnittestLite.optionalInt32ExtensionLite, 123)
+ .addExtension(UnittestLite.repeatedStringExtensionLite, "hello")
+ .setExtension(UnittestLite.optionalNestedEnumExtensionLite,
+ TestAllTypesLite.NestedEnum.BAZ)
+ .setExtension(UnittestLite.optionalNestedMessageExtensionLite,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(7).build())
+ .build();
+
+ // Test copying a message, since coping extensions actually does use a
+ // different code path between lite and regular libraries, and as of this
+ // writing, parsing hasn't been implemented yet.
+ TestAllExtensionsLite message2 = message.toBuilder().build();
+
+ assertEquals(123, (int) message2.getExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+ assertEquals(1, message2.getExtensionCount(
+ UnittestLite.repeatedStringExtensionLite));
+ assertEquals("hello", message2.getExtension(
+ UnittestLite.repeatedStringExtensionLite, 0));
+ assertEquals(TestAllTypesLite.NestedEnum.BAZ, message2.getExtension(
+ UnittestLite.optionalNestedEnumExtensionLite));
+ assertEquals(7, message2.getExtension(
+ UnittestLite.optionalNestedMessageExtensionLite).getBb());
+ }
+}
diff --git a/java/src/test/java/com/google/protobuf/TestUtil.java b/java/src/test/java/com/google/protobuf/TestUtil.java
index 2f47b714..805c42ae 100644
--- a/java/src/test/java/com/google/protobuf/TestUtil.java
+++ b/java/src/test/java/com/google/protobuf/TestUtil.java
@@ -31,6 +31,7 @@
package com.google.protobuf;
import protobuf_unittest.UnittestProto;
+import com.google.protobuf.UnittestLite;
// The static imports are to avoid 100+ char lines. The following is roughly equivalent to
// import static protobuf_unittest.UnittestProto.*;
@@ -123,6 +124,95 @@ import static protobuf_unittest.UnittestProto.packedDoubleExtension;
import static protobuf_unittest.UnittestProto.packedBoolExtension;
import static protobuf_unittest.UnittestProto.packedEnumExtension;
+import static com.google.protobuf.UnittestLite.defaultInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultStringExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultNestedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultForeignEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultStringPieceExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultCordExtensionLite;
+
+import static com.google.protobuf.UnittestLite.optionalInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalStringExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalGroupExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalNestedMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalForeignMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalNestedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalForeignEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalStringPieceExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalCordExtensionLite;
+
+import static com.google.protobuf.UnittestLite.repeatedInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedStringExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedGroupExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedNestedMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedForeignMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedNestedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedForeignEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedStringPieceExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedCordExtensionLite;
+
+import static com.google.protobuf.UnittestLite.OptionalGroup_extension_lite;
+import static com.google.protobuf.UnittestLite.RepeatedGroup_extension_lite;
+
+import static com.google.protobuf.UnittestLite.packedInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.packedDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.packedBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.packedEnumExtensionLite;
+
import protobuf_unittest.UnittestProto.TestAllExtensions;
import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestPackedExtensions;
@@ -132,6 +222,14 @@ import protobuf_unittest.UnittestProto.ForeignEnum;
import com.google.protobuf.test.UnittestImport.ImportMessage;
import com.google.protobuf.test.UnittestImport.ImportEnum;
+import com.google.protobuf.UnittestLite.TestAllTypesLite;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
+import com.google.protobuf.UnittestLite.ForeignMessageLite;
+import com.google.protobuf.UnittestLite.ForeignEnumLite;
+import com.google.protobuf.UnittestImportLite.ImportMessageLite;
+import com.google.protobuf.UnittestImportLite.ImportEnumLite;
+
import junit.framework.Assert;
import java.io.File;
@@ -179,6 +277,12 @@ class TestUtil {
return builder.build();
}
+ public static TestAllExtensionsLite getAllLiteExtensionsSet() {
+ TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder();
+ setAllExtensions(builder);
+ return builder.build();
+ }
+
public static TestPackedTypes getPackedSet() {
TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
setPackedFields(builder);
@@ -191,6 +295,13 @@ class TestUtil {
return builder.build();
}
+ public static TestPackedExtensionsLite getLitePackedExtensionsSet() {
+ TestPackedExtensionsLite.Builder builder =
+ TestPackedExtensionsLite.newBuilder();
+ setPackedExtensions(builder);
+ return builder.build();
+ }
+
/**
* Set every field of {@code message} to the values expected by
* {@code assertAllFieldsSet()}.
@@ -809,6 +920,90 @@ class TestUtil {
Assert.assertEquals("525", message.getRepeatedCord(1));
}
+ /**
+ * Set every field of {@code message} to a unique value.
+ */
+ public static void setPackedFields(TestPackedTypes.Builder message) {
+ message.addPackedInt32 (601);
+ message.addPackedInt64 (602);
+ message.addPackedUint32 (603);
+ message.addPackedUint64 (604);
+ message.addPackedSint32 (605);
+ message.addPackedSint64 (606);
+ message.addPackedFixed32 (607);
+ message.addPackedFixed64 (608);
+ message.addPackedSfixed32(609);
+ message.addPackedSfixed64(610);
+ message.addPackedFloat (611);
+ message.addPackedDouble (612);
+ message.addPackedBool (true);
+ message.addPackedEnum (ForeignEnum.FOREIGN_BAR);
+ // Add a second one of each field.
+ message.addPackedInt32 (701);
+ message.addPackedInt64 (702);
+ message.addPackedUint32 (703);
+ message.addPackedUint64 (704);
+ message.addPackedSint32 (705);
+ message.addPackedSint64 (706);
+ message.addPackedFixed32 (707);
+ message.addPackedFixed64 (708);
+ message.addPackedSfixed32(709);
+ message.addPackedSfixed64(710);
+ message.addPackedFloat (711);
+ message.addPackedDouble (712);
+ message.addPackedBool (false);
+ message.addPackedEnum (ForeignEnum.FOREIGN_BAZ);
+ }
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all fields of
+ * {@code message} are set to the values assigned by {@code setPackedFields}.
+ */
+ public static void assertPackedFieldsSet(TestPackedTypes message) {
+ Assert.assertEquals(2, message.getPackedInt32Count ());
+ Assert.assertEquals(2, message.getPackedInt64Count ());
+ Assert.assertEquals(2, message.getPackedUint32Count ());
+ Assert.assertEquals(2, message.getPackedUint64Count ());
+ Assert.assertEquals(2, message.getPackedSint32Count ());
+ Assert.assertEquals(2, message.getPackedSint64Count ());
+ Assert.assertEquals(2, message.getPackedFixed32Count ());
+ Assert.assertEquals(2, message.getPackedFixed64Count ());
+ Assert.assertEquals(2, message.getPackedSfixed32Count());
+ Assert.assertEquals(2, message.getPackedSfixed64Count());
+ Assert.assertEquals(2, message.getPackedFloatCount ());
+ Assert.assertEquals(2, message.getPackedDoubleCount ());
+ Assert.assertEquals(2, message.getPackedBoolCount ());
+ Assert.assertEquals(2, message.getPackedEnumCount ());
+ Assert.assertEquals(601 , message.getPackedInt32 (0));
+ Assert.assertEquals(602 , message.getPackedInt64 (0));
+ Assert.assertEquals(603 , message.getPackedUint32 (0));
+ Assert.assertEquals(604 , message.getPackedUint64 (0));
+ Assert.assertEquals(605 , message.getPackedSint32 (0));
+ Assert.assertEquals(606 , message.getPackedSint64 (0));
+ Assert.assertEquals(607 , message.getPackedFixed32 (0));
+ Assert.assertEquals(608 , message.getPackedFixed64 (0));
+ Assert.assertEquals(609 , message.getPackedSfixed32(0));
+ Assert.assertEquals(610 , message.getPackedSfixed64(0));
+ Assert.assertEquals(611 , message.getPackedFloat (0), 0.0);
+ Assert.assertEquals(612 , message.getPackedDouble (0), 0.0);
+ Assert.assertEquals(true , message.getPackedBool (0));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getPackedEnum(0));
+ Assert.assertEquals(701 , message.getPackedInt32 (1));
+ Assert.assertEquals(702 , message.getPackedInt64 (1));
+ Assert.assertEquals(703 , message.getPackedUint32 (1));
+ Assert.assertEquals(704 , message.getPackedUint64 (1));
+ Assert.assertEquals(705 , message.getPackedSint32 (1));
+ Assert.assertEquals(706 , message.getPackedSint64 (1));
+ Assert.assertEquals(707 , message.getPackedFixed32 (1));
+ Assert.assertEquals(708 , message.getPackedFixed64 (1));
+ Assert.assertEquals(709 , message.getPackedSfixed32(1));
+ Assert.assertEquals(710 , message.getPackedSfixed64(1));
+ Assert.assertEquals(711 , message.getPackedFloat (1), 0.0);
+ Assert.assertEquals(712 , message.getPackedDouble (1), 0.0);
+ Assert.assertEquals(false, message.getPackedBool (1));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getPackedEnum(1));
+ }
+
// ===================================================================
// Like above, but for extensions
@@ -846,6 +1041,18 @@ class TestUtil {
private static void assertEqualsExactType(ImportEnum a, ImportEnum b) {
Assert.assertEquals(a, b);
}
+ private static void assertEqualsExactType(TestAllTypesLite.NestedEnum a,
+ TestAllTypesLite.NestedEnum b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(ForeignEnumLite a,
+ ForeignEnumLite b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(ImportEnumLite a,
+ ImportEnumLite b) {
+ Assert.assertEquals(a, b);
+ }
/**
* Get an unmodifiable {@link ExtensionRegistry} containing all the
@@ -857,12 +1064,23 @@ class TestUtil {
return registry.getUnmodifiable();
}
+ public static ExtensionRegistryLite getExtensionRegistryLite() {
+ ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance();
+ registerAllExtensionsLite(registry);
+ return registry.getUnmodifiable();
+ }
+
/**
- * Register all of {@code TestAllExtensions}' extensions with the
+ * Register all of {@code TestAllExtensions}'s extensions with the
* given {@link ExtensionRegistry}.
*/
public static void registerAllExtensions(ExtensionRegistry registry) {
UnittestProto.registerAllExtensions(registry);
+ registerAllExtensionsLite(registry);
+ }
+
+ public static void registerAllExtensionsLite(ExtensionRegistryLite registry) {
+ UnittestLite.registerAllExtensions(registry);
}
/**
@@ -1509,90 +1727,6 @@ class TestUtil {
assertEqualsExactType("525", message.getExtension(repeatedCordExtension, 1));
}
- /**
- * Set every field of {@code message} to a unique value.
- */
- public static void setPackedFields(TestPackedTypes.Builder message) {
- message.addPackedInt32 (601);
- message.addPackedInt64 (602);
- message.addPackedUint32 (603);
- message.addPackedUint64 (604);
- message.addPackedSint32 (605);
- message.addPackedSint64 (606);
- message.addPackedFixed32 (607);
- message.addPackedFixed64 (608);
- message.addPackedSfixed32(609);
- message.addPackedSfixed64(610);
- message.addPackedFloat (611);
- message.addPackedDouble (612);
- message.addPackedBool (true);
- message.addPackedEnum (ForeignEnum.FOREIGN_BAR);
- // Add a second one of each field.
- message.addPackedInt32 (701);
- message.addPackedInt64 (702);
- message.addPackedUint32 (703);
- message.addPackedUint64 (704);
- message.addPackedSint32 (705);
- message.addPackedSint64 (706);
- message.addPackedFixed32 (707);
- message.addPackedFixed64 (708);
- message.addPackedSfixed32(709);
- message.addPackedSfixed64(710);
- message.addPackedFloat (711);
- message.addPackedDouble (712);
- message.addPackedBool (false);
- message.addPackedEnum (ForeignEnum.FOREIGN_BAZ);
- }
-
- /**
- * Assert (using {@code junit.framework.Assert}} that all fields of
- * {@code message} are set to the values assigned by {@code setPackedFields}.
- */
- public static void assertPackedFieldsSet(TestPackedTypes message) {
- Assert.assertEquals(2, message.getPackedInt32Count ());
- Assert.assertEquals(2, message.getPackedInt64Count ());
- Assert.assertEquals(2, message.getPackedUint32Count ());
- Assert.assertEquals(2, message.getPackedUint64Count ());
- Assert.assertEquals(2, message.getPackedSint32Count ());
- Assert.assertEquals(2, message.getPackedSint64Count ());
- Assert.assertEquals(2, message.getPackedFixed32Count ());
- Assert.assertEquals(2, message.getPackedFixed64Count ());
- Assert.assertEquals(2, message.getPackedSfixed32Count());
- Assert.assertEquals(2, message.getPackedSfixed64Count());
- Assert.assertEquals(2, message.getPackedFloatCount ());
- Assert.assertEquals(2, message.getPackedDoubleCount ());
- Assert.assertEquals(2, message.getPackedBoolCount ());
- Assert.assertEquals(2, message.getPackedEnumCount ());
- Assert.assertEquals(601 , message.getPackedInt32 (0));
- Assert.assertEquals(602 , message.getPackedInt64 (0));
- Assert.assertEquals(603 , message.getPackedUint32 (0));
- Assert.assertEquals(604 , message.getPackedUint64 (0));
- Assert.assertEquals(605 , message.getPackedSint32 (0));
- Assert.assertEquals(606 , message.getPackedSint64 (0));
- Assert.assertEquals(607 , message.getPackedFixed32 (0));
- Assert.assertEquals(608 , message.getPackedFixed64 (0));
- Assert.assertEquals(609 , message.getPackedSfixed32(0));
- Assert.assertEquals(610 , message.getPackedSfixed64(0));
- Assert.assertEquals(611 , message.getPackedFloat (0), 0.0);
- Assert.assertEquals(612 , message.getPackedDouble (0), 0.0);
- Assert.assertEquals(true , message.getPackedBool (0));
- Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getPackedEnum(0));
- Assert.assertEquals(701 , message.getPackedInt32 (1));
- Assert.assertEquals(702 , message.getPackedInt64 (1));
- Assert.assertEquals(703 , message.getPackedUint32 (1));
- Assert.assertEquals(704 , message.getPackedUint64 (1));
- Assert.assertEquals(705 , message.getPackedSint32 (1));
- Assert.assertEquals(706 , message.getPackedSint64 (1));
- Assert.assertEquals(707 , message.getPackedFixed32 (1));
- Assert.assertEquals(708 , message.getPackedFixed64 (1));
- Assert.assertEquals(709 , message.getPackedSfixed32(1));
- Assert.assertEquals(710 , message.getPackedSfixed64(1));
- Assert.assertEquals(711 , message.getPackedFloat (1), 0.0);
- Assert.assertEquals(712 , message.getPackedDouble (1), 0.0);
- Assert.assertEquals(false, message.getPackedBool (1));
- Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getPackedEnum(1));
- }
-
public static void setPackedExtensions(TestPackedExtensions.Builder message) {
message.addExtension(packedInt32Extension , 601);
message.addExtension(packedInt64Extension , 602L);
@@ -1672,8 +1806,733 @@ class TestUtil {
message.getExtension(packedEnumExtension, 1));
}
-
// ===================================================================
+ // Lite extensions
+
+ /**
+ * Set every field of {@code message} to the values expected by
+ * {@code assertAllExtensionsSet()}.
+ */
+ public static void setAllExtensions(TestAllExtensionsLite.Builder message) {
+ message.setExtension(optionalInt32ExtensionLite , 101);
+ message.setExtension(optionalInt64ExtensionLite , 102L);
+ message.setExtension(optionalUint32ExtensionLite , 103);
+ message.setExtension(optionalUint64ExtensionLite , 104L);
+ message.setExtension(optionalSint32ExtensionLite , 105);
+ message.setExtension(optionalSint64ExtensionLite , 106L);
+ message.setExtension(optionalFixed32ExtensionLite , 107);
+ message.setExtension(optionalFixed64ExtensionLite , 108L);
+ message.setExtension(optionalSfixed32ExtensionLite, 109);
+ message.setExtension(optionalSfixed64ExtensionLite, 110L);
+ message.setExtension(optionalFloatExtensionLite , 111F);
+ message.setExtension(optionalDoubleExtensionLite , 112D);
+ message.setExtension(optionalBoolExtensionLite , true);
+ message.setExtension(optionalStringExtensionLite , "115");
+ message.setExtension(optionalBytesExtensionLite , toBytes("116"));
+
+ message.setExtension(optionalGroupExtensionLite,
+ OptionalGroup_extension_lite.newBuilder().setA(117).build());
+ message.setExtension(optionalNestedMessageExtensionLite,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(118).build());
+ message.setExtension(optionalForeignMessageExtensionLite,
+ ForeignMessageLite.newBuilder().setC(119).build());
+ message.setExtension(optionalImportMessageExtensionLite,
+ ImportMessageLite.newBuilder().setD(120).build());
+
+ message.setExtension(optionalNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ);
+ message.setExtension(optionalForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ);
+ message.setExtension(optionalImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAZ);
+
+ message.setExtension(optionalStringPieceExtensionLite, "124");
+ message.setExtension(optionalCordExtensionLite, "125");
+
+ // -----------------------------------------------------------------
+
+ message.addExtension(repeatedInt32ExtensionLite , 201);
+ message.addExtension(repeatedInt64ExtensionLite , 202L);
+ message.addExtension(repeatedUint32ExtensionLite , 203);
+ message.addExtension(repeatedUint64ExtensionLite , 204L);
+ message.addExtension(repeatedSint32ExtensionLite , 205);
+ message.addExtension(repeatedSint64ExtensionLite , 206L);
+ message.addExtension(repeatedFixed32ExtensionLite , 207);
+ message.addExtension(repeatedFixed64ExtensionLite , 208L);
+ message.addExtension(repeatedSfixed32ExtensionLite, 209);
+ message.addExtension(repeatedSfixed64ExtensionLite, 210L);
+ message.addExtension(repeatedFloatExtensionLite , 211F);
+ message.addExtension(repeatedDoubleExtensionLite , 212D);
+ message.addExtension(repeatedBoolExtensionLite , true);
+ message.addExtension(repeatedStringExtensionLite , "215");
+ message.addExtension(repeatedBytesExtensionLite , toBytes("216"));
+
+ message.addExtension(repeatedGroupExtensionLite,
+ RepeatedGroup_extension_lite.newBuilder().setA(217).build());
+ message.addExtension(repeatedNestedMessageExtensionLite,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(218).build());
+ message.addExtension(repeatedForeignMessageExtensionLite,
+ ForeignMessageLite.newBuilder().setC(219).build());
+ message.addExtension(repeatedImportMessageExtensionLite,
+ ImportMessageLite.newBuilder().setD(220).build());
+
+ message.addExtension(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAR);
+ message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAR);
+ message.addExtension(repeatedImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAR);
+
+ message.addExtension(repeatedStringPieceExtensionLite, "224");
+ message.addExtension(repeatedCordExtensionLite, "225");
+
+ // Add a second one of each field.
+ message.addExtension(repeatedInt32ExtensionLite , 301);
+ message.addExtension(repeatedInt64ExtensionLite , 302L);
+ message.addExtension(repeatedUint32ExtensionLite , 303);
+ message.addExtension(repeatedUint64ExtensionLite , 304L);
+ message.addExtension(repeatedSint32ExtensionLite , 305);
+ message.addExtension(repeatedSint64ExtensionLite , 306L);
+ message.addExtension(repeatedFixed32ExtensionLite , 307);
+ message.addExtension(repeatedFixed64ExtensionLite , 308L);
+ message.addExtension(repeatedSfixed32ExtensionLite, 309);
+ message.addExtension(repeatedSfixed64ExtensionLite, 310L);
+ message.addExtension(repeatedFloatExtensionLite , 311F);
+ message.addExtension(repeatedDoubleExtensionLite , 312D);
+ message.addExtension(repeatedBoolExtensionLite , false);
+ message.addExtension(repeatedStringExtensionLite , "315");
+ message.addExtension(repeatedBytesExtensionLite , toBytes("316"));
+
+ message.addExtension(repeatedGroupExtensionLite,
+ RepeatedGroup_extension_lite.newBuilder().setA(317).build());
+ message.addExtension(repeatedNestedMessageExtensionLite,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(318).build());
+ message.addExtension(repeatedForeignMessageExtensionLite,
+ ForeignMessageLite.newBuilder().setC(319).build());
+ message.addExtension(repeatedImportMessageExtensionLite,
+ ImportMessageLite.newBuilder().setD(320).build());
+
+ message.addExtension(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ);
+ message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ);
+ message.addExtension(repeatedImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAZ);
+
+ message.addExtension(repeatedStringPieceExtensionLite, "324");
+ message.addExtension(repeatedCordExtensionLite, "325");
+
+ // -----------------------------------------------------------------
+
+ message.setExtension(defaultInt32ExtensionLite , 401);
+ message.setExtension(defaultInt64ExtensionLite , 402L);
+ message.setExtension(defaultUint32ExtensionLite , 403);
+ message.setExtension(defaultUint64ExtensionLite , 404L);
+ message.setExtension(defaultSint32ExtensionLite , 405);
+ message.setExtension(defaultSint64ExtensionLite , 406L);
+ message.setExtension(defaultFixed32ExtensionLite , 407);
+ message.setExtension(defaultFixed64ExtensionLite , 408L);
+ message.setExtension(defaultSfixed32ExtensionLite, 409);
+ message.setExtension(defaultSfixed64ExtensionLite, 410L);
+ message.setExtension(defaultFloatExtensionLite , 411F);
+ message.setExtension(defaultDoubleExtensionLite , 412D);
+ message.setExtension(defaultBoolExtensionLite , false);
+ message.setExtension(defaultStringExtensionLite , "415");
+ message.setExtension(defaultBytesExtensionLite , toBytes("416"));
+
+ message.setExtension(defaultNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.FOO);
+ message.setExtension(defaultForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_FOO);
+ message.setExtension(defaultImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_FOO);
+
+ message.setExtension(defaultStringPieceExtensionLite, "424");
+ message.setExtension(defaultCordExtensionLite, "425");
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Modify the repeated extensions of {@code message} to contain the values
+ * expected by {@code assertRepeatedExtensionsModified()}.
+ */
+ public static void modifyRepeatedExtensions(
+ TestAllExtensionsLite.Builder message) {
+ message.setExtension(repeatedInt32ExtensionLite , 1, 501);
+ message.setExtension(repeatedInt64ExtensionLite , 1, 502L);
+ message.setExtension(repeatedUint32ExtensionLite , 1, 503);
+ message.setExtension(repeatedUint64ExtensionLite , 1, 504L);
+ message.setExtension(repeatedSint32ExtensionLite , 1, 505);
+ message.setExtension(repeatedSint64ExtensionLite , 1, 506L);
+ message.setExtension(repeatedFixed32ExtensionLite , 1, 507);
+ message.setExtension(repeatedFixed64ExtensionLite , 1, 508L);
+ message.setExtension(repeatedSfixed32ExtensionLite, 1, 509);
+ message.setExtension(repeatedSfixed64ExtensionLite, 1, 510L);
+ message.setExtension(repeatedFloatExtensionLite , 1, 511F);
+ message.setExtension(repeatedDoubleExtensionLite , 1, 512D);
+ message.setExtension(repeatedBoolExtensionLite , 1, true);
+ message.setExtension(repeatedStringExtensionLite , 1, "515");
+ message.setExtension(repeatedBytesExtensionLite , 1, toBytes("516"));
+
+ message.setExtension(repeatedGroupExtensionLite, 1,
+ RepeatedGroup_extension_lite.newBuilder().setA(517).build());
+ message.setExtension(repeatedNestedMessageExtensionLite, 1,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(518).build());
+ message.setExtension(repeatedForeignMessageExtensionLite, 1,
+ ForeignMessageLite.newBuilder().setC(519).build());
+ message.setExtension(repeatedImportMessageExtensionLite, 1,
+ ImportMessageLite.newBuilder().setD(520).build());
+
+ message.setExtension(repeatedNestedEnumExtensionLite , 1, TestAllTypesLite.NestedEnum.FOO);
+ message.setExtension(repeatedForeignEnumExtensionLite, 1, ForeignEnumLite.FOREIGN_LITE_FOO);
+ message.setExtension(repeatedImportEnumExtensionLite , 1, ImportEnumLite.IMPORT_LITE_FOO);
+
+ message.setExtension(repeatedStringPieceExtensionLite, 1, "524");
+ message.setExtension(repeatedCordExtensionLite, 1, "525");
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all extensions of
+ * {@code message} are set to the values assigned by {@code setAllExtensions}.
+ */
+ public static void assertAllExtensionsSet(TestAllExtensionsLite message) {
+ Assert.assertTrue(message.hasExtension(optionalInt32ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalInt64ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalUint32ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalUint64ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalSint32ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalSint64ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalFixed32ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalFixed64ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalSfixed32ExtensionLite));
+ Assert.assertTrue(message.hasExtension(optionalSfixed64ExtensionLite));
+ Assert.assertTrue(message.hasExtension(optionalFloatExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalDoubleExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalBoolExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalStringExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalBytesExtensionLite ));
+
+ Assert.assertTrue(message.hasExtension(optionalGroupExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalNestedMessageExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalForeignMessageExtensionLite));
+ Assert.assertTrue(message.hasExtension(optionalImportMessageExtensionLite ));
+
+ Assert.assertTrue(message.getExtension(optionalGroupExtensionLite ).hasA());
+ Assert.assertTrue(message.getExtension(optionalNestedMessageExtensionLite ).hasBb());
+ Assert.assertTrue(message.getExtension(optionalForeignMessageExtensionLite).hasC());
+ Assert.assertTrue(message.getExtension(optionalImportMessageExtensionLite ).hasD());
+
+ Assert.assertTrue(message.hasExtension(optionalNestedEnumExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalForeignEnumExtensionLite));
+ Assert.assertTrue(message.hasExtension(optionalImportEnumExtensionLite ));
+
+ Assert.assertTrue(message.hasExtension(optionalStringPieceExtensionLite));
+ Assert.assertTrue(message.hasExtension(optionalCordExtensionLite));
+
+ assertEqualsExactType(101 , message.getExtension(optionalInt32ExtensionLite ));
+ assertEqualsExactType(102L , message.getExtension(optionalInt64ExtensionLite ));
+ assertEqualsExactType(103 , message.getExtension(optionalUint32ExtensionLite ));
+ assertEqualsExactType(104L , message.getExtension(optionalUint64ExtensionLite ));
+ assertEqualsExactType(105 , message.getExtension(optionalSint32ExtensionLite ));
+ assertEqualsExactType(106L , message.getExtension(optionalSint64ExtensionLite ));
+ assertEqualsExactType(107 , message.getExtension(optionalFixed32ExtensionLite ));
+ assertEqualsExactType(108L , message.getExtension(optionalFixed64ExtensionLite ));
+ assertEqualsExactType(109 , message.getExtension(optionalSfixed32ExtensionLite));
+ assertEqualsExactType(110L , message.getExtension(optionalSfixed64ExtensionLite));
+ assertEqualsExactType(111F , message.getExtension(optionalFloatExtensionLite ));
+ assertEqualsExactType(112D , message.getExtension(optionalDoubleExtensionLite ));
+ assertEqualsExactType(true , message.getExtension(optionalBoolExtensionLite ));
+ assertEqualsExactType("115", message.getExtension(optionalStringExtensionLite ));
+ assertEqualsExactType(toBytes("116"), message.getExtension(optionalBytesExtensionLite));
+
+ assertEqualsExactType(117, message.getExtension(optionalGroupExtensionLite ).getA());
+ assertEqualsExactType(118, message.getExtension(optionalNestedMessageExtensionLite ).getBb());
+ assertEqualsExactType(119, message.getExtension(optionalForeignMessageExtensionLite).getC());
+ assertEqualsExactType(120, message.getExtension(optionalImportMessageExtensionLite ).getD());
+
+ assertEqualsExactType(TestAllTypesLite.NestedEnum.BAZ,
+ message.getExtension(optionalNestedEnumExtensionLite));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAZ,
+ message.getExtension(optionalForeignEnumExtensionLite));
+ assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAZ,
+ message.getExtension(optionalImportEnumExtensionLite));
+
+ assertEqualsExactType("124", message.getExtension(optionalStringPieceExtensionLite));
+ assertEqualsExactType("125", message.getExtension(optionalCordExtensionLite));
+
+ // -----------------------------------------------------------------
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32ExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64ExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtensionLite ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtensionLite ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtensionLite));
+
+ assertEqualsExactType(201 , message.getExtension(repeatedInt32ExtensionLite , 0));
+ assertEqualsExactType(202L , message.getExtension(repeatedInt64ExtensionLite , 0));
+ assertEqualsExactType(203 , message.getExtension(repeatedUint32ExtensionLite , 0));
+ assertEqualsExactType(204L , message.getExtension(repeatedUint64ExtensionLite , 0));
+ assertEqualsExactType(205 , message.getExtension(repeatedSint32ExtensionLite , 0));
+ assertEqualsExactType(206L , message.getExtension(repeatedSint64ExtensionLite , 0));
+ assertEqualsExactType(207 , message.getExtension(repeatedFixed32ExtensionLite , 0));
+ assertEqualsExactType(208L , message.getExtension(repeatedFixed64ExtensionLite , 0));
+ assertEqualsExactType(209 , message.getExtension(repeatedSfixed32ExtensionLite, 0));
+ assertEqualsExactType(210L , message.getExtension(repeatedSfixed64ExtensionLite, 0));
+ assertEqualsExactType(211F , message.getExtension(repeatedFloatExtensionLite , 0));
+ assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtensionLite , 0));
+ assertEqualsExactType(true , message.getExtension(repeatedBoolExtensionLite , 0));
+ assertEqualsExactType("215", message.getExtension(repeatedStringExtensionLite , 0));
+ assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtensionLite, 0));
+
+ assertEqualsExactType(217, message.getExtension(repeatedGroupExtensionLite ,0).getA());
+ assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtensionLite ,0).getBb());
+ assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtensionLite,0).getC());
+ assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtensionLite ,0).getD());
+
+ assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR,
+ message.getExtension(repeatedNestedEnumExtensionLite, 0));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR,
+ message.getExtension(repeatedForeignEnumExtensionLite, 0));
+ assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAR,
+ message.getExtension(repeatedImportEnumExtensionLite, 0));
+
+ assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtensionLite, 0));
+ assertEqualsExactType("225", message.getExtension(repeatedCordExtensionLite, 0));
+
+ assertEqualsExactType(301 , message.getExtension(repeatedInt32ExtensionLite , 1));
+ assertEqualsExactType(302L , message.getExtension(repeatedInt64ExtensionLite , 1));
+ assertEqualsExactType(303 , message.getExtension(repeatedUint32ExtensionLite , 1));
+ assertEqualsExactType(304L , message.getExtension(repeatedUint64ExtensionLite , 1));
+ assertEqualsExactType(305 , message.getExtension(repeatedSint32ExtensionLite , 1));
+ assertEqualsExactType(306L , message.getExtension(repeatedSint64ExtensionLite , 1));
+ assertEqualsExactType(307 , message.getExtension(repeatedFixed32ExtensionLite , 1));
+ assertEqualsExactType(308L , message.getExtension(repeatedFixed64ExtensionLite , 1));
+ assertEqualsExactType(309 , message.getExtension(repeatedSfixed32ExtensionLite, 1));
+ assertEqualsExactType(310L , message.getExtension(repeatedSfixed64ExtensionLite, 1));
+ assertEqualsExactType(311F , message.getExtension(repeatedFloatExtensionLite , 1));
+ assertEqualsExactType(312D , message.getExtension(repeatedDoubleExtensionLite , 1));
+ assertEqualsExactType(false, message.getExtension(repeatedBoolExtensionLite , 1));
+ assertEqualsExactType("315", message.getExtension(repeatedStringExtensionLite , 1));
+ assertEqualsExactType(toBytes("316"), message.getExtension(repeatedBytesExtensionLite, 1));
+
+ assertEqualsExactType(317, message.getExtension(repeatedGroupExtensionLite ,1).getA());
+ assertEqualsExactType(318, message.getExtension(repeatedNestedMessageExtensionLite ,1).getBb());
+ assertEqualsExactType(319, message.getExtension(repeatedForeignMessageExtensionLite,1).getC());
+ assertEqualsExactType(320, message.getExtension(repeatedImportMessageExtensionLite ,1).getD());
+
+ assertEqualsExactType(TestAllTypesLite.NestedEnum.BAZ,
+ message.getExtension(repeatedNestedEnumExtensionLite, 1));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAZ,
+ message.getExtension(repeatedForeignEnumExtensionLite, 1));
+ assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAZ,
+ message.getExtension(repeatedImportEnumExtensionLite, 1));
+
+ assertEqualsExactType("324", message.getExtension(repeatedStringPieceExtensionLite, 1));
+ assertEqualsExactType("325", message.getExtension(repeatedCordExtensionLite, 1));
+
+ // -----------------------------------------------------------------
+
+ Assert.assertTrue(message.hasExtension(defaultInt32ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultInt64ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultUint32ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultUint64ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultSint32ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultSint64ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultFixed32ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultFixed64ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultSfixed32ExtensionLite));
+ Assert.assertTrue(message.hasExtension(defaultSfixed64ExtensionLite));
+ Assert.assertTrue(message.hasExtension(defaultFloatExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultDoubleExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultBoolExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultStringExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultBytesExtensionLite ));
+
+ Assert.assertTrue(message.hasExtension(defaultNestedEnumExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultForeignEnumExtensionLite));
+ Assert.assertTrue(message.hasExtension(defaultImportEnumExtensionLite ));
+
+ Assert.assertTrue(message.hasExtension(defaultStringPieceExtensionLite));
+ Assert.assertTrue(message.hasExtension(defaultCordExtensionLite));
+
+ assertEqualsExactType(401 , message.getExtension(defaultInt32ExtensionLite ));
+ assertEqualsExactType(402L , message.getExtension(defaultInt64ExtensionLite ));
+ assertEqualsExactType(403 , message.getExtension(defaultUint32ExtensionLite ));
+ assertEqualsExactType(404L , message.getExtension(defaultUint64ExtensionLite ));
+ assertEqualsExactType(405 , message.getExtension(defaultSint32ExtensionLite ));
+ assertEqualsExactType(406L , message.getExtension(defaultSint64ExtensionLite ));
+ assertEqualsExactType(407 , message.getExtension(defaultFixed32ExtensionLite ));
+ assertEqualsExactType(408L , message.getExtension(defaultFixed64ExtensionLite ));
+ assertEqualsExactType(409 , message.getExtension(defaultSfixed32ExtensionLite));
+ assertEqualsExactType(410L , message.getExtension(defaultSfixed64ExtensionLite));
+ assertEqualsExactType(411F , message.getExtension(defaultFloatExtensionLite ));
+ assertEqualsExactType(412D , message.getExtension(defaultDoubleExtensionLite ));
+ assertEqualsExactType(false, message.getExtension(defaultBoolExtensionLite ));
+ assertEqualsExactType("415", message.getExtension(defaultStringExtensionLite ));
+ assertEqualsExactType(toBytes("416"), message.getExtension(defaultBytesExtensionLite));
+
+ assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO,
+ message.getExtension(defaultNestedEnumExtensionLite ));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_FOO,
+ message.getExtension(defaultForeignEnumExtensionLite));
+ assertEqualsExactType(ImportEnumLite.IMPORT_LITE_FOO,
+ message.getExtension(defaultImportEnumExtensionLite));
+
+ assertEqualsExactType("424", message.getExtension(defaultStringPieceExtensionLite));
+ assertEqualsExactType("425", message.getExtension(defaultCordExtensionLite));
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all extensions of
+ * {@code message} are cleared, and that getting the extensions returns their
+ * default values.
+ */
+ public static void assertExtensionsClear(TestAllExtensionsLite message) {
+ // hasBlah() should initially be false for all optional fields.
+ Assert.assertFalse(message.hasExtension(optionalInt32ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalInt64ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalUint32ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalUint64ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalSint32ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalSint64ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalFixed32ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalFixed64ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalSfixed32ExtensionLite));
+ Assert.assertFalse(message.hasExtension(optionalSfixed64ExtensionLite));
+ Assert.assertFalse(message.hasExtension(optionalFloatExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalDoubleExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalBoolExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalStringExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalBytesExtensionLite ));
+
+ Assert.assertFalse(message.hasExtension(optionalGroupExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalNestedMessageExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalForeignMessageExtensionLite));
+ Assert.assertFalse(message.hasExtension(optionalImportMessageExtensionLite ));
+
+ Assert.assertFalse(message.hasExtension(optionalNestedEnumExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalForeignEnumExtensionLite));
+ Assert.assertFalse(message.hasExtension(optionalImportEnumExtensionLite ));
+
+ Assert.assertFalse(message.hasExtension(optionalStringPieceExtensionLite));
+ Assert.assertFalse(message.hasExtension(optionalCordExtensionLite));
+
+ // Optional fields without defaults are set to zero or something like it.
+ assertEqualsExactType(0 , message.getExtension(optionalInt32ExtensionLite ));
+ assertEqualsExactType(0L , message.getExtension(optionalInt64ExtensionLite ));
+ assertEqualsExactType(0 , message.getExtension(optionalUint32ExtensionLite ));
+ assertEqualsExactType(0L , message.getExtension(optionalUint64ExtensionLite ));
+ assertEqualsExactType(0 , message.getExtension(optionalSint32ExtensionLite ));
+ assertEqualsExactType(0L , message.getExtension(optionalSint64ExtensionLite ));
+ assertEqualsExactType(0 , message.getExtension(optionalFixed32ExtensionLite ));
+ assertEqualsExactType(0L , message.getExtension(optionalFixed64ExtensionLite ));
+ assertEqualsExactType(0 , message.getExtension(optionalSfixed32ExtensionLite));
+ assertEqualsExactType(0L , message.getExtension(optionalSfixed64ExtensionLite));
+ assertEqualsExactType(0F , message.getExtension(optionalFloatExtensionLite ));
+ assertEqualsExactType(0D , message.getExtension(optionalDoubleExtensionLite ));
+ assertEqualsExactType(false, message.getExtension(optionalBoolExtensionLite ));
+ assertEqualsExactType("" , message.getExtension(optionalStringExtensionLite ));
+ assertEqualsExactType(ByteString.EMPTY, message.getExtension(optionalBytesExtensionLite));
+
+ // Embedded messages should also be clear.
+ Assert.assertFalse(message.getExtension(optionalGroupExtensionLite ).hasA());
+ Assert.assertFalse(message.getExtension(optionalNestedMessageExtensionLite ).hasBb());
+ Assert.assertFalse(message.getExtension(optionalForeignMessageExtensionLite).hasC());
+ Assert.assertFalse(message.getExtension(optionalImportMessageExtensionLite ).hasD());
+
+ assertEqualsExactType(0, message.getExtension(optionalGroupExtensionLite ).getA());
+ assertEqualsExactType(0, message.getExtension(optionalNestedMessageExtensionLite ).getBb());
+ assertEqualsExactType(0, message.getExtension(optionalForeignMessageExtensionLite).getC());
+ assertEqualsExactType(0, message.getExtension(optionalImportMessageExtensionLite ).getD());
+
+ // Enums without defaults are set to the first value in the enum.
+ assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO,
+ message.getExtension(optionalNestedEnumExtensionLite ));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_FOO,
+ message.getExtension(optionalForeignEnumExtensionLite));
+ assertEqualsExactType(ImportEnumLite.IMPORT_LITE_FOO,
+ message.getExtension(optionalImportEnumExtensionLite));
+
+ assertEqualsExactType("", message.getExtension(optionalStringPieceExtensionLite));
+ assertEqualsExactType("", message.getExtension(optionalCordExtensionLite));
+
+ // Repeated fields are empty.
+ Assert.assertEquals(0, message.getExtensionCount(repeatedInt32ExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedInt64ExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedUint32ExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedUint64ExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSint32ExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSint64ExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedFixed32ExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedFixed64ExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed32ExtensionLite));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed64ExtensionLite));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedFloatExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedDoubleExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedBoolExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedStringExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedBytesExtensionLite ));
+
+ Assert.assertEquals(0, message.getExtensionCount(repeatedGroupExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedNestedMessageExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedForeignMessageExtensionLite));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedImportMessageExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedNestedEnumExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedForeignEnumExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedImportEnumExtensionLite ));
+
+ Assert.assertEquals(0, message.getExtensionCount(repeatedStringPieceExtensionLite));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedCordExtensionLite));
+
+ // hasBlah() should also be false for all default fields.
+ Assert.assertFalse(message.hasExtension(defaultInt32ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultInt64ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultUint32ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultUint64ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultSint32ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultSint64ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultFixed32ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultFixed64ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultSfixed32ExtensionLite));
+ Assert.assertFalse(message.hasExtension(defaultSfixed64ExtensionLite));
+ Assert.assertFalse(message.hasExtension(defaultFloatExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultDoubleExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultBoolExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultStringExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultBytesExtensionLite ));
+
+ Assert.assertFalse(message.hasExtension(defaultNestedEnumExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultForeignEnumExtensionLite));
+ Assert.assertFalse(message.hasExtension(defaultImportEnumExtensionLite ));
+
+ Assert.assertFalse(message.hasExtension(defaultStringPieceExtensionLite));
+ Assert.assertFalse(message.hasExtension(defaultCordExtensionLite));
+
+ // Fields with defaults have their default values (duh).
+ assertEqualsExactType( 41 , message.getExtension(defaultInt32ExtensionLite ));
+ assertEqualsExactType( 42L , message.getExtension(defaultInt64ExtensionLite ));
+ assertEqualsExactType( 43 , message.getExtension(defaultUint32ExtensionLite ));
+ assertEqualsExactType( 44L , message.getExtension(defaultUint64ExtensionLite ));
+ assertEqualsExactType(-45 , message.getExtension(defaultSint32ExtensionLite ));
+ assertEqualsExactType( 46L , message.getExtension(defaultSint64ExtensionLite ));
+ assertEqualsExactType( 47 , message.getExtension(defaultFixed32ExtensionLite ));
+ assertEqualsExactType( 48L , message.getExtension(defaultFixed64ExtensionLite ));
+ assertEqualsExactType( 49 , message.getExtension(defaultSfixed32ExtensionLite));
+ assertEqualsExactType(-50L , message.getExtension(defaultSfixed64ExtensionLite));
+ assertEqualsExactType( 51.5F , message.getExtension(defaultFloatExtensionLite ));
+ assertEqualsExactType( 52e3D , message.getExtension(defaultDoubleExtensionLite ));
+ assertEqualsExactType(true , message.getExtension(defaultBoolExtensionLite ));
+ assertEqualsExactType("hello", message.getExtension(defaultStringExtensionLite ));
+ assertEqualsExactType(toBytes("world"), message.getExtension(defaultBytesExtensionLite));
+
+ assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR,
+ message.getExtension(defaultNestedEnumExtensionLite ));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR,
+ message.getExtension(defaultForeignEnumExtensionLite));
+ assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAR,
+ message.getExtension(defaultImportEnumExtensionLite));
+
+ assertEqualsExactType("abc", message.getExtension(defaultStringPieceExtensionLite));
+ assertEqualsExactType("123", message.getExtension(defaultCordExtensionLite));
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all extensions of
+ * {@code message} are set to the values assigned by {@code setAllExtensions}
+ * followed by {@code modifyRepeatedExtensions}.
+ */
+ public static void assertRepeatedExtensionsModified(
+ TestAllExtensionsLite message) {
+ // ModifyRepeatedFields only sets the second repeated element of each
+ // field. In addition to verifying this, we also verify that the first
+ // element and size were *not* modified.
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32ExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64ExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtensionLite ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtensionLite ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtensionLite));
+
+ assertEqualsExactType(201 , message.getExtension(repeatedInt32ExtensionLite , 0));
+ assertEqualsExactType(202L , message.getExtension(repeatedInt64ExtensionLite , 0));
+ assertEqualsExactType(203 , message.getExtension(repeatedUint32ExtensionLite , 0));
+ assertEqualsExactType(204L , message.getExtension(repeatedUint64ExtensionLite , 0));
+ assertEqualsExactType(205 , message.getExtension(repeatedSint32ExtensionLite , 0));
+ assertEqualsExactType(206L , message.getExtension(repeatedSint64ExtensionLite , 0));
+ assertEqualsExactType(207 , message.getExtension(repeatedFixed32ExtensionLite , 0));
+ assertEqualsExactType(208L , message.getExtension(repeatedFixed64ExtensionLite , 0));
+ assertEqualsExactType(209 , message.getExtension(repeatedSfixed32ExtensionLite, 0));
+ assertEqualsExactType(210L , message.getExtension(repeatedSfixed64ExtensionLite, 0));
+ assertEqualsExactType(211F , message.getExtension(repeatedFloatExtensionLite , 0));
+ assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtensionLite , 0));
+ assertEqualsExactType(true , message.getExtension(repeatedBoolExtensionLite , 0));
+ assertEqualsExactType("215", message.getExtension(repeatedStringExtensionLite , 0));
+ assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtensionLite, 0));
+
+ assertEqualsExactType(217, message.getExtension(repeatedGroupExtensionLite ,0).getA());
+ assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtensionLite ,0).getBb());
+ assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtensionLite,0).getC());
+ assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtensionLite ,0).getD());
+
+ assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR,
+ message.getExtension(repeatedNestedEnumExtensionLite, 0));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR,
+ message.getExtension(repeatedForeignEnumExtensionLite, 0));
+ assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAR,
+ message.getExtension(repeatedImportEnumExtensionLite, 0));
+
+ assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtensionLite, 0));
+ assertEqualsExactType("225", message.getExtension(repeatedCordExtensionLite, 0));
+
+ // Actually verify the second (modified) elements now.
+ assertEqualsExactType(501 , message.getExtension(repeatedInt32ExtensionLite , 1));
+ assertEqualsExactType(502L , message.getExtension(repeatedInt64ExtensionLite , 1));
+ assertEqualsExactType(503 , message.getExtension(repeatedUint32ExtensionLite , 1));
+ assertEqualsExactType(504L , message.getExtension(repeatedUint64ExtensionLite , 1));
+ assertEqualsExactType(505 , message.getExtension(repeatedSint32ExtensionLite , 1));
+ assertEqualsExactType(506L , message.getExtension(repeatedSint64ExtensionLite , 1));
+ assertEqualsExactType(507 , message.getExtension(repeatedFixed32ExtensionLite , 1));
+ assertEqualsExactType(508L , message.getExtension(repeatedFixed64ExtensionLite , 1));
+ assertEqualsExactType(509 , message.getExtension(repeatedSfixed32ExtensionLite, 1));
+ assertEqualsExactType(510L , message.getExtension(repeatedSfixed64ExtensionLite, 1));
+ assertEqualsExactType(511F , message.getExtension(repeatedFloatExtensionLite , 1));
+ assertEqualsExactType(512D , message.getExtension(repeatedDoubleExtensionLite , 1));
+ assertEqualsExactType(true , message.getExtension(repeatedBoolExtensionLite , 1));
+ assertEqualsExactType("515", message.getExtension(repeatedStringExtensionLite , 1));
+ assertEqualsExactType(toBytes("516"), message.getExtension(repeatedBytesExtensionLite, 1));
+
+ assertEqualsExactType(517, message.getExtension(repeatedGroupExtensionLite ,1).getA());
+ assertEqualsExactType(518, message.getExtension(repeatedNestedMessageExtensionLite ,1).getBb());
+ assertEqualsExactType(519, message.getExtension(repeatedForeignMessageExtensionLite,1).getC());
+ assertEqualsExactType(520, message.getExtension(repeatedImportMessageExtensionLite ,1).getD());
+
+ assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO,
+ message.getExtension(repeatedNestedEnumExtensionLite, 1));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_FOO,
+ message.getExtension(repeatedForeignEnumExtensionLite, 1));
+ assertEqualsExactType(ImportEnumLite.IMPORT_LITE_FOO,
+ message.getExtension(repeatedImportEnumExtensionLite, 1));
+
+ assertEqualsExactType("524", message.getExtension(repeatedStringPieceExtensionLite, 1));
+ assertEqualsExactType("525", message.getExtension(repeatedCordExtensionLite, 1));
+ }
+
+ public static void setPackedExtensions(TestPackedExtensionsLite.Builder message) {
+ message.addExtension(packedInt32ExtensionLite , 601);
+ message.addExtension(packedInt64ExtensionLite , 602L);
+ message.addExtension(packedUint32ExtensionLite , 603);
+ message.addExtension(packedUint64ExtensionLite , 604L);
+ message.addExtension(packedSint32ExtensionLite , 605);
+ message.addExtension(packedSint64ExtensionLite , 606L);
+ message.addExtension(packedFixed32ExtensionLite , 607);
+ message.addExtension(packedFixed64ExtensionLite , 608L);
+ message.addExtension(packedSfixed32ExtensionLite, 609);
+ message.addExtension(packedSfixed64ExtensionLite, 610L);
+ message.addExtension(packedFloatExtensionLite , 611F);
+ message.addExtension(packedDoubleExtensionLite , 612D);
+ message.addExtension(packedBoolExtensionLite , true);
+ message.addExtension(packedEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAR);
+ // Add a second one of each field.
+ message.addExtension(packedInt32ExtensionLite , 701);
+ message.addExtension(packedInt64ExtensionLite , 702L);
+ message.addExtension(packedUint32ExtensionLite , 703);
+ message.addExtension(packedUint64ExtensionLite , 704L);
+ message.addExtension(packedSint32ExtensionLite , 705);
+ message.addExtension(packedSint64ExtensionLite , 706L);
+ message.addExtension(packedFixed32ExtensionLite , 707);
+ message.addExtension(packedFixed64ExtensionLite , 708L);
+ message.addExtension(packedSfixed32ExtensionLite, 709);
+ message.addExtension(packedSfixed64ExtensionLite, 710L);
+ message.addExtension(packedFloatExtensionLite , 711F);
+ message.addExtension(packedDoubleExtensionLite , 712D);
+ message.addExtension(packedBoolExtensionLite , false);
+ message.addExtension(packedEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ);
+ }
+
+ public static void assertPackedExtensionsSet(TestPackedExtensionsLite message) {
+ Assert.assertEquals(2, message.getExtensionCount(packedInt32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedInt64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedUint32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedUint64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedSint32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedSint64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedFixed32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedFixed64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedSfixed32ExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(packedSfixed64ExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(packedFloatExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedDoubleExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedBoolExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedEnumExtensionLite));
+ assertEqualsExactType(601 , message.getExtension(packedInt32ExtensionLite , 0));
+ assertEqualsExactType(602L , message.getExtension(packedInt64ExtensionLite , 0));
+ assertEqualsExactType(603 , message.getExtension(packedUint32ExtensionLite , 0));
+ assertEqualsExactType(604L , message.getExtension(packedUint64ExtensionLite , 0));
+ assertEqualsExactType(605 , message.getExtension(packedSint32ExtensionLite , 0));
+ assertEqualsExactType(606L , message.getExtension(packedSint64ExtensionLite , 0));
+ assertEqualsExactType(607 , message.getExtension(packedFixed32ExtensionLite , 0));
+ assertEqualsExactType(608L , message.getExtension(packedFixed64ExtensionLite , 0));
+ assertEqualsExactType(609 , message.getExtension(packedSfixed32ExtensionLite, 0));
+ assertEqualsExactType(610L , message.getExtension(packedSfixed64ExtensionLite, 0));
+ assertEqualsExactType(611F , message.getExtension(packedFloatExtensionLite , 0));
+ assertEqualsExactType(612D , message.getExtension(packedDoubleExtensionLite , 0));
+ assertEqualsExactType(true , message.getExtension(packedBoolExtensionLite , 0));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR,
+ message.getExtension(packedEnumExtensionLite, 0));
+ assertEqualsExactType(701 , message.getExtension(packedInt32ExtensionLite , 1));
+ assertEqualsExactType(702L , message.getExtension(packedInt64ExtensionLite , 1));
+ assertEqualsExactType(703 , message.getExtension(packedUint32ExtensionLite , 1));
+ assertEqualsExactType(704L , message.getExtension(packedUint64ExtensionLite , 1));
+ assertEqualsExactType(705 , message.getExtension(packedSint32ExtensionLite , 1));
+ assertEqualsExactType(706L , message.getExtension(packedSint64ExtensionLite , 1));
+ assertEqualsExactType(707 , message.getExtension(packedFixed32ExtensionLite , 1));
+ assertEqualsExactType(708L , message.getExtension(packedFixed64ExtensionLite , 1));
+ assertEqualsExactType(709 , message.getExtension(packedSfixed32ExtensionLite, 1));
+ assertEqualsExactType(710L , message.getExtension(packedSfixed64ExtensionLite, 1));
+ assertEqualsExactType(711F , message.getExtension(packedFloatExtensionLite , 1));
+ assertEqualsExactType(712D , message.getExtension(packedDoubleExtensionLite , 1));
+ assertEqualsExactType(false, message.getExtension(packedBoolExtensionLite , 1));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAZ,
+ message.getExtension(packedEnumExtensionLite, 1));
+ }
+
+ // =================================================================
/**
* Performs the same things that the methods of {@code TestUtil} do, but
diff --git a/java/src/test/java/com/google/protobuf/TextFormatTest.java b/java/src/test/java/com/google/protobuf/TextFormatTest.java
index ec4910a3..1d73165e 100644
--- a/java/src/test/java/com/google/protobuf/TextFormatTest.java
+++ b/java/src/test/java/com/google/protobuf/TextFormatTest.java
@@ -30,9 +30,12 @@
package com.google.protobuf;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import protobuf_unittest.UnittestProto.OneString;
import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestAllExtensions;
import protobuf_unittest.UnittestProto.TestEmptyMessage;
+import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
import protobuf_unittest.UnittestMset.TestMessageSet;
import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
@@ -173,6 +176,22 @@ public class TextFormatTest extends TestCase {
TextFormat.printToString(message));
}
+ public void testPrintField() throws Exception {
+ final FieldDescriptor dataField =
+ OneString.getDescriptor().findFieldByName("data");
+ assertEquals(
+ "data: \"test data\"\n",
+ TextFormat.printFieldToString(dataField, "test data"));
+
+ final FieldDescriptor optionalField =
+ TestAllTypes.getDescriptor().findFieldByName("optional_nested_message");
+ final Object value = NestedMessage.newBuilder().setBb(42).build();
+
+ assertEquals(
+ "optional_nested_message {\n bb: 42\n}\n",
+ TextFormat.printFieldToString(optionalField, value));
+ }
+
/**
* Helper to construct a ByteString from a String containing only 8-bit
* characters. The characters are converted directly to bytes, *not*
@@ -450,21 +469,21 @@ public class TextFormatTest extends TestCase {
try {
TextFormat.unescapeText("\\x");
fail("Should have thrown an exception.");
- } catch (TextFormat.InvalidEscapeSequence e) {
+ } catch (TextFormat.InvalidEscapeSequenceException e) {
// success
}
try {
TextFormat.unescapeText("\\z");
fail("Should have thrown an exception.");
- } catch (TextFormat.InvalidEscapeSequence e) {
+ } catch (TextFormat.InvalidEscapeSequenceException e) {
// success
}
try {
TextFormat.unescapeText("\\");
fail("Should have thrown an exception.");
- } catch (TextFormat.InvalidEscapeSequence e) {
+ } catch (TextFormat.InvalidEscapeSequenceException e) {
// success
}
}
diff --git a/java/src/test/java/com/google/protobuf/WireFormatTest.java b/java/src/test/java/com/google/protobuf/WireFormatTest.java
index 4afefdb6..bd1c6db1 100644
--- a/java/src/test/java/com/google/protobuf/WireFormatTest.java
+++ b/java/src/test/java/com/google/protobuf/WireFormatTest.java
@@ -45,6 +45,8 @@ import protobuf_unittest.UnittestMset.TestMessageSet;
import protobuf_unittest.UnittestMset.RawMessageSet;
import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
/**
* Tests related to parsing and serialization.
@@ -100,6 +102,32 @@ public class WireFormatTest extends TestCase {
assertEquals(rawBytes, rawBytes2);
}
+ public void testSerializeExtensionsLite() throws Exception {
+ // TestAllTypes and TestAllExtensions should have compatible wire formats,
+ // so if we serialize a TestAllExtensions then parse it as TestAllTypes
+ // it should work.
+
+ TestAllExtensionsLite message = TestUtil.getAllLiteExtensionsSet();
+ ByteString rawBytes = message.toByteString();
+ assertEquals(rawBytes.size(), message.getSerializedSize());
+
+ TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
+
+ TestUtil.assertAllFieldsSet(message2);
+ }
+
+ public void testSerializePackedExtensionsLite() throws Exception {
+ // TestPackedTypes and TestPackedExtensions should have compatible wire
+ // formats; check that they serialize to the same string.
+ TestPackedExtensionsLite message = TestUtil.getLitePackedExtensionsSet();
+ ByteString rawBytes = message.toByteString();
+
+ TestPackedTypes message2 = TestUtil.getPackedSet();
+ ByteString rawBytes2 = message2.toByteString();
+
+ assertEquals(rawBytes, rawBytes2);
+ }
+
public void testParseExtensions() throws Exception {
// TestAllTypes and TestAllExtensions should have compatible wire formats,
// so if we serialize a TestAllTypes then parse it as TestAllExtensions
@@ -129,6 +157,43 @@ public class WireFormatTest extends TestCase {
TestUtil.assertPackedExtensionsSet(message2);
}
+ public void testParseExtensionsLite() throws Exception {
+ // TestAllTypes and TestAllExtensions should have compatible wire formats,
+ // so if we serialize a TestAllTypes then parse it as TestAllExtensions
+ // it should work.
+
+ TestAllTypes message = TestUtil.getAllSet();
+ ByteString rawBytes = message.toByteString();
+
+ ExtensionRegistryLite registry_lite = TestUtil.getExtensionRegistryLite();
+
+ TestAllExtensionsLite message2 =
+ TestAllExtensionsLite.parseFrom(rawBytes, registry_lite);
+
+ TestUtil.assertAllExtensionsSet(message2);
+
+ // Try again using a full extension registry.
+ ExtensionRegistry registry = TestUtil.getExtensionRegistry();
+
+ TestAllExtensionsLite message3 =
+ TestAllExtensionsLite.parseFrom(rawBytes, registry);
+
+ TestUtil.assertAllExtensionsSet(message3);
+ }
+
+ public void testParsePackedExtensionsLite() throws Exception {
+ // Ensure that packed extensions can be properly parsed.
+ TestPackedExtensionsLite message = TestUtil.getLitePackedExtensionsSet();
+ ByteString rawBytes = message.toByteString();
+
+ ExtensionRegistryLite registry = TestUtil.getExtensionRegistryLite();
+
+ TestPackedExtensionsLite message2 =
+ TestPackedExtensionsLite.parseFrom(rawBytes, registry);
+
+ TestUtil.assertPackedExtensionsSet(message2);
+ }
+
public void testExtensionsSerializedSize() throws Exception {
assertEquals(TestUtil.getAllSet().getSerializedSize(),
TestUtil.getAllExtensionsSet().getSerializedSize());