summaryrefslogtreecommitdiffstats
path: root/java/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java')
-rw-r--r--java/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java108
1 files changed, 89 insertions, 19 deletions
diff --git a/java/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java b/java/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java
index 63c8afc..46cd86f 100644
--- a/java/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java
+++ b/java/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java
@@ -31,8 +31,6 @@
package com.google.protobuf.nano;
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
/**
* Base class of those Protocol Buffer messages that need to store unknown fields,
@@ -44,42 +42,79 @@ public abstract class ExtendableMessageNano<M extends ExtendableMessageNano<M>>
* A container for fields unknown to the message, including extensions. Extension fields can
* can be accessed through the {@link #getExtension} and {@link #setExtension} methods.
*/
- protected List<UnknownFieldData> unknownFieldData;
+ protected FieldArray unknownFieldData;
@Override
protected int computeSerializedSize() {
int size = 0;
- int unknownFieldCount = unknownFieldData == null ? 0 : unknownFieldData.size();
- for (int i = 0; i < unknownFieldCount; i++) {
- UnknownFieldData unknownField = unknownFieldData.get(i);
- size += CodedOutputByteBufferNano.computeRawVarint32Size(unknownField.tag);
- size += unknownField.bytes.length;
+ if (unknownFieldData != null) {
+ for (int i = 0; i < unknownFieldData.size(); i++) {
+ FieldData field = unknownFieldData.dataAt(i);
+ size += field.computeSerializedSize();
+ }
}
return size;
}
@Override
public void writeTo(CodedOutputByteBufferNano output) throws IOException {
- int unknownFieldCount = unknownFieldData == null ? 0 : unknownFieldData.size();
- for (int i = 0; i < unknownFieldCount; i++) {
- UnknownFieldData unknownField = unknownFieldData.get(i);
- output.writeRawVarint32(unknownField.tag);
- output.writeRawBytes(unknownField.bytes);
+ if (unknownFieldData == null) {
+ return;
+ }
+ for (int i = 0; i < unknownFieldData.size(); i++) {
+ FieldData field = unknownFieldData.dataAt(i);
+ field.writeTo(output);
+ }
+ }
+
+ /**
+ * Checks if there is a value stored for the specified extension in this
+ * message.
+ */
+ public final boolean hasExtension(Extension<M, ?> extension) {
+ if (unknownFieldData == null) {
+ return false;
}
+ FieldData field = unknownFieldData.get(WireFormatNano.getTagFieldNumber(extension.tag));
+ return field != null;
}
/**
* Gets the value stored in the specified extension of this message.
*/
public final <T> T getExtension(Extension<M, T> extension) {
- return extension.getValueFrom(unknownFieldData);
+ if (unknownFieldData == null) {
+ return null;
+ }
+ FieldData field = unknownFieldData.get(WireFormatNano.getTagFieldNumber(extension.tag));
+ return field == null ? null : field.getValue(extension);
}
/**
* Sets the value of the specified extension of this message.
*/
public final <T> M setExtension(Extension<M, T> extension, T value) {
- unknownFieldData = extension.setValueTo(value, unknownFieldData);
+ int fieldNumber = WireFormatNano.getTagFieldNumber(extension.tag);
+ if (value == null) {
+ if (unknownFieldData != null) {
+ unknownFieldData.remove(fieldNumber);
+ if (unknownFieldData.isEmpty()) {
+ unknownFieldData = null;
+ }
+ }
+ } else {
+ FieldData field = null;
+ if (unknownFieldData == null) {
+ unknownFieldData = new FieldArray();
+ } else {
+ field = unknownFieldData.get(fieldNumber);
+ }
+ if (field == null) {
+ unknownFieldData.put(fieldNumber, new FieldData(extension, value));
+ } else {
+ field.setValue(extension, value);
+ }
+ }
@SuppressWarnings("unchecked") // Generated code should guarantee type safety
M typedThis = (M) this;
@@ -106,12 +141,47 @@ public abstract class ExtendableMessageNano<M extends ExtendableMessageNano<M>>
if (!input.skipField(tag)) {
return false; // This wasn't an unknown field, it's an end-group tag.
}
- if (unknownFieldData == null) {
- unknownFieldData = new ArrayList<UnknownFieldData>();
- }
+ int fieldNumber = WireFormatNano.getTagFieldNumber(tag);
int endPos = input.getPosition();
byte[] bytes = input.getData(startPos, endPos - startPos);
- unknownFieldData.add(new UnknownFieldData(tag, bytes));
+ UnknownFieldData unknownField = new UnknownFieldData(tag, bytes);
+
+ FieldData field = null;
+ if (unknownFieldData == null) {
+ unknownFieldData = new FieldArray();
+ } else {
+ field = unknownFieldData.get(fieldNumber);
+ }
+ if (field == null) {
+ field = new FieldData();
+ unknownFieldData.put(fieldNumber, field);
+ }
+ field.addUnknownField(unknownField);
return true;
}
+
+ /**
+ * Returns whether the stored unknown field data in this message is equivalent to that in the
+ * other message.
+ *
+ * @param other the other message.
+ * @return whether the two sets of unknown field data are equal.
+ */
+ protected final boolean unknownFieldDataEquals(M other) {
+ if (unknownFieldData == null || unknownFieldData.isEmpty()) {
+ return other.unknownFieldData == null || other.unknownFieldData.isEmpty();
+ } else {
+ return unknownFieldData.equals(other.unknownFieldData);
+ }
+ }
+
+ /**
+ * Computes the hashcode representing the unknown field data stored in this message.
+ *
+ * @return the hashcode for the unknown field data.
+ */
+ protected final int unknownFieldDataHashCode() {
+ return (unknownFieldData == null || unknownFieldData.isEmpty()
+ ? 0 : unknownFieldData.hashCode());
+ }
}