summaryrefslogtreecommitdiffstats
path: root/java/src/main/java/com/google/protobuf/nano
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/main/java/com/google/protobuf/nano')
-rw-r--r--java/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java259
-rw-r--r--java/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java40
-rw-r--r--java/src/main/java/com/google/protobuf/nano/Extension.java35
-rw-r--r--java/src/main/java/com/google/protobuf/nano/FieldArray.java34
-rw-r--r--java/src/main/java/com/google/protobuf/nano/FieldData.java69
-rw-r--r--java/src/main/java/com/google/protobuf/nano/InternalNano.java8
-rw-r--r--java/src/main/java/com/google/protobuf/nano/MessageNano.java34
-rw-r--r--java/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java6
-rw-r--r--java/src/main/java/com/google/protobuf/nano/UnknownFieldData.java4
-rw-r--r--java/src/main/java/com/google/protobuf/nano/WireFormatNano.java6
10 files changed, 74 insertions, 421 deletions
diff --git a/java/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java b/java/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java
index 324a63f..88df38d 100644
--- a/java/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java
+++ b/java/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java
@@ -31,9 +31,7 @@
package com.google.protobuf.nano;
import java.io.IOException;
-import java.nio.BufferOverflowException;
-import java.nio.ByteBuffer;
-import java.nio.ReadOnlyBufferException;
+import java.io.UnsupportedEncodingException;
/**
* Encodes and writes protocol message fields.
@@ -50,17 +48,15 @@ import java.nio.ReadOnlyBufferException;
* @author kneton@google.com Kenton Varda
*/
public final class CodedOutputByteBufferNano {
- /* max bytes per java UTF-16 char in UTF-8 */
- private static final int MAX_UTF8_EXPANSION = 3;
- private final ByteBuffer buffer;
+ private final byte[] buffer;
+ private final int limit;
+ private int position;
private CodedOutputByteBufferNano(final byte[] buffer, final int offset,
final int length) {
- this(ByteBuffer.wrap(buffer, offset, length));
- }
-
- private CodedOutputByteBufferNano(final ByteBuffer buffer) {
this.buffer = buffer;
+ position = offset;
+ limit = offset + length;
}
/**
@@ -292,203 +288,14 @@ public final class CodedOutputByteBufferNano {
/** Write a {@code string} field to the stream. */
public void writeStringNoTag(final String value) throws IOException {
- // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()),
- // and at most 3 times of it. Optimize for the case where we know this length results in a
- // constant varint length - saves measuring length of the string.
- try {
- final int minLengthVarIntSize = computeRawVarint32Size(value.length());
- final int maxLengthVarIntSize = computeRawVarint32Size(value.length() * MAX_UTF8_EXPANSION);
- if (minLengthVarIntSize == maxLengthVarIntSize) {
- int oldPosition = buffer.position();
- buffer.position(oldPosition + minLengthVarIntSize);
- encode(value, buffer);
- int newPosition = buffer.position();
- buffer.position(oldPosition);
- writeRawVarint32(newPosition - oldPosition - minLengthVarIntSize);
- buffer.position(newPosition);
- } else {
- writeRawVarint32(encodedLength(value));
- encode(value, buffer);
- }
- } catch (BufferOverflowException e) {
- throw new OutOfSpaceException(buffer.position(), buffer.limit());
- }
- }
-
- // These UTF-8 handling methods are copied from Guava's Utf8 class.
- /**
- * Returns the number of bytes in the UTF-8-encoded form of {@code sequence}. For a string,
- * this method is equivalent to {@code string.getBytes(UTF_8).length}, but is more efficient in
- * both time and space.
- *
- * @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired
- * surrogates)
- */
- private static int encodedLength(CharSequence sequence) {
- // Warning to maintainers: this implementation is highly optimized.
- int utf16Length = sequence.length();
- int utf8Length = utf16Length;
- int i = 0;
-
- // This loop optimizes for pure ASCII.
- while (i < utf16Length && sequence.charAt(i) < 0x80) {
- i++;
- }
-
- // This loop optimizes for chars less than 0x800.
- for (; i < utf16Length; i++) {
- char c = sequence.charAt(i);
- if (c < 0x800) {
- utf8Length += ((0x7f - c) >>> 31); // branch free!
- } else {
- utf8Length += encodedLengthGeneral(sequence, i);
- break;
- }
- }
-
- if (utf8Length < utf16Length) {
- // Necessary and sufficient condition for overflow because of maximum 3x expansion
- throw new IllegalArgumentException("UTF-8 length does not fit in int: "
- + (utf8Length + (1L << 32)));
- }
- return utf8Length;
- }
-
- private static int encodedLengthGeneral(CharSequence sequence, int start) {
- int utf16Length = sequence.length();
- int utf8Length = 0;
- for (int i = start; i < utf16Length; i++) {
- char c = sequence.charAt(i);
- if (c < 0x800) {
- utf8Length += (0x7f - c) >>> 31; // branch free!
- } else {
- utf8Length += 2;
- // jdk7+: if (Character.isSurrogate(c)) {
- if (Character.MIN_SURROGATE <= c && c <= Character.MAX_SURROGATE) {
- // Check that we have a well-formed surrogate pair.
- int cp = Character.codePointAt(sequence, i);
- if (cp < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
- throw new IllegalArgumentException("Unpaired surrogate at index " + i);
- }
- i++;
- }
- }
- }
- return utf8Length;
- }
-
- /**
- * Encodes {@code sequence} into UTF-8, in {@code byteBuffer}. For a string, this method is
- * equivalent to {@code buffer.put(string.getBytes(UTF_8))}, but is more efficient in both time
- * and space. Bytes are written starting at the current position. This method requires paired
- * surrogates, and therefore does not support chunking.
- *
- * <p>To ensure sufficient space in the output buffer, either call {@link #encodedLength} to
- * compute the exact amount needed, or leave room for {@code 3 * sequence.length()}, which is the
- * largest possible number of bytes that any input can be encoded to.
- *
- * @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired
- * surrogates)
- * @throws BufferOverflowException if {@code sequence} encoded in UTF-8 does not fit in
- * {@code byteBuffer}'s remaining space.
- * @throws ReadOnlyBufferException if {@code byteBuffer} is a read-only buffer.
- */
- private static void encode(CharSequence sequence, ByteBuffer byteBuffer) {
- if (byteBuffer.isReadOnly()) {
- throw new ReadOnlyBufferException();
- } else if (byteBuffer.hasArray()) {
- try {
- int encoded = encode(sequence,
- byteBuffer.array(),
- byteBuffer.arrayOffset() + byteBuffer.position(),
- byteBuffer.remaining());
- byteBuffer.position(encoded - byteBuffer.arrayOffset());
- } catch (ArrayIndexOutOfBoundsException e) {
- BufferOverflowException boe = new BufferOverflowException();
- boe.initCause(e);
- throw boe;
- }
- } else {
- encodeDirect(sequence, byteBuffer);
- }
- }
-
- private static void encodeDirect(CharSequence sequence, ByteBuffer byteBuffer) {
- int utf16Length = sequence.length();
- for (int i = 0; i < utf16Length; i++) {
- final char c = sequence.charAt(i);
- if (c < 0x80) { // ASCII
- byteBuffer.put((byte) c);
- } else if (c < 0x800) { // 11 bits, two UTF-8 bytes
- byteBuffer.put((byte) ((0xF << 6) | (c >>> 6)));
- byteBuffer.put((byte) (0x80 | (0x3F & c)));
- } else if (c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) {
- // Maximium single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
- byteBuffer.put((byte) ((0xF << 5) | (c >>> 12)));
- byteBuffer.put((byte) (0x80 | (0x3F & (c >>> 6))));
- byteBuffer.put((byte) (0x80 | (0x3F & c)));
- } else {
- final char low;
- if (i + 1 == sequence.length()
- || !Character.isSurrogatePair(c, (low = sequence.charAt(++i)))) {
- throw new IllegalArgumentException("Unpaired surrogate at index " + (i - 1));
- }
- int codePoint = Character.toCodePoint(c, low);
- byteBuffer.put((byte) ((0xF << 4) | (codePoint >>> 18)));
- byteBuffer.put((byte) (0x80 | (0x3F & (codePoint >>> 12))));
- byteBuffer.put((byte) (0x80 | (0x3F & (codePoint >>> 6))));
- byteBuffer.put((byte) (0x80 | (0x3F & codePoint)));
- }
- }
- }
-
- private static int encode(CharSequence sequence, byte[] bytes, int offset, int length) {
- int utf16Length = sequence.length();
- int j = offset;
- int i = 0;
- int limit = offset + length;
- // Designed to take advantage of
- // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
- for (char c; i < utf16Length && i + j < limit && (c = sequence.charAt(i)) < 0x80; i++) {
- bytes[j + i] = (byte) c;
- }
- if (i == utf16Length) {
- return j + utf16Length;
- }
- j += i;
- for (char c; i < utf16Length; i++) {
- c = sequence.charAt(i);
- if (c < 0x80 && j < limit) {
- bytes[j++] = (byte) c;
- } else if (c < 0x800 && j <= limit - 2) { // 11 bits, two UTF-8 bytes
- bytes[j++] = (byte) ((0xF << 6) | (c >>> 6));
- bytes[j++] = (byte) (0x80 | (0x3F & c));
- } else if ((c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) && j <= limit - 3) {
- // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
- bytes[j++] = (byte) ((0xF << 5) | (c >>> 12));
- bytes[j++] = (byte) (0x80 | (0x3F & (c >>> 6)));
- bytes[j++] = (byte) (0x80 | (0x3F & c));
- } else if (j <= limit - 4) {
- // Minimum code point represented by a surrogate pair is 0x10000, 17 bits, four UTF-8 bytes
- final char low;
- if (i + 1 == sequence.length()
- || !Character.isSurrogatePair(c, (low = sequence.charAt(++i)))) {
- throw new IllegalArgumentException("Unpaired surrogate at index " + (i - 1));
- }
- int codePoint = Character.toCodePoint(c, low);
- bytes[j++] = (byte) ((0xF << 4) | (codePoint >>> 18));
- bytes[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 12)));
- bytes[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 6)));
- bytes[j++] = (byte) (0x80 | (0x3F & codePoint));
- } else {
- throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + j);
- }
- }
- return j;
+ // 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.
+ final byte[] bytes = value.getBytes("UTF-8");
+ writeRawVarint32(bytes.length);
+ writeRawBytes(bytes);
}
- // End guava UTF-8 methods
-
/** Write a {@code group} field to the stream. */
public void writeGroupNoTag(final MessageNano value) throws IOException {
value.writeTo(this);
@@ -796,8 +603,13 @@ public final class CodedOutputByteBufferNano {
* {@code string} field.
*/
public static int computeStringSizeNoTag(final String value) {
- final int length = encodedLength(value);
- return computeRawVarint32Size(length) + length;
+ try {
+ final byte[] bytes = value.getBytes("UTF-8");
+ return computeRawVarint32Size(bytes.length) +
+ bytes.length;
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException("UTF-8 not supported.");
+ }
}
/**
@@ -880,7 +692,7 @@ public final class CodedOutputByteBufferNano {
* Otherwise, throws {@code UnsupportedOperationException}.
*/
public int spaceLeft() {
- return buffer.remaining();
+ return limit - position;
}
/**
@@ -898,23 +710,6 @@ public final class CodedOutputByteBufferNano {
}
/**
- * Returns the position within the internal buffer.
- */
- public int position() {
- return buffer.position();
- }
-
- /**
- * Resets the position within the internal buffer to zero.
- *
- * @see #position
- * @see #spaceLeft
- */
- public void reset() {
- buffer.clear();
- }
-
- /**
* If you create a CodedOutputStream around a simple flat array, you must
* not attempt to write more bytes than the array has space. Otherwise,
* this exception will be thrown.
@@ -930,12 +725,12 @@ public final class CodedOutputByteBufferNano {
/** Write a single byte. */
public void writeRawByte(final byte value) throws IOException {
- if (!buffer.hasRemaining()) {
+ if (position == limit) {
// We're writing to a single buffer.
- throw new OutOfSpaceException(buffer.position(), buffer.limit());
+ throw new OutOfSpaceException(position, limit);
}
- buffer.put(value);
+ buffer[position++] = value;
}
/** Write a single byte, represented by an integer value. */
@@ -951,11 +746,13 @@ public final class CodedOutputByteBufferNano {
/** Write part of an array of bytes. */
public void writeRawBytes(final byte[] value, int offset, int length)
throws IOException {
- if (buffer.remaining() >= length) {
- buffer.put(value, offset, length);
+ if (limit - position >= length) {
+ // We have room in the current buffer.
+ System.arraycopy(value, offset, buffer, position, length);
+ position += length;
} else {
// We're writing to a single buffer.
- throw new OutOfSpaceException(buffer.position(), buffer.limit());
+ throw new OutOfSpaceException(position, limit);
}
}
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 4fe8dce..5984d35 100644
--- a/java/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java
+++ b/java/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java
@@ -68,18 +68,6 @@ public abstract class ExtendableMessageNano<M extends ExtendableMessageNano<M>>
}
/**
- * 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) {
@@ -160,10 +148,28 @@ public abstract class ExtendableMessageNano<M extends ExtendableMessageNano<M>>
return true;
}
- @Override
- public M clone() throws CloneNotSupportedException {
- M cloned = (M) super.clone();
- InternalNano.cloneUnknownFieldData(this, cloned);
- return cloned;
+ /**
+ * 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());
}
}
diff --git a/java/src/main/java/com/google/protobuf/nano/Extension.java b/java/src/main/java/com/google/protobuf/nano/Extension.java
index 6e2202e..962f66e 100644
--- a/java/src/main/java/com/google/protobuf/nano/Extension.java
+++ b/java/src/main/java/com/google/protobuf/nano/Extension.java
@@ -79,30 +79,12 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
* Should be used by the generated code only.
*
* @param type {@link #TYPE_MESSAGE} or {@link #TYPE_GROUP}
- * @deprecated use {@link #createMessageTyped(int, Class, long)} instead.
*/
- @Deprecated
public static <M extends ExtendableMessageNano<M>, T extends MessageNano>
Extension<M, T> createMessageTyped(int type, Class<T> clazz, int tag) {
return new Extension<M, T>(type, clazz, tag, false);
}
- // Note: these create...() methods take a long for the tag parameter,
- // because tags are represented as unsigned ints, and these values exist
- // in generated code as long values. However, they can fit in 32-bits, so
- // it's safe to cast them to int without loss of precision.
-
- /**
- * Creates an {@code Extension} of the given message type and tag number.
- * Should be used by the generated code only.
- *
- * @param type {@link #TYPE_MESSAGE} or {@link #TYPE_GROUP}
- */
- public static <M extends ExtendableMessageNano<M>, T extends MessageNano>
- Extension<M, T> createMessageTyped(int type, Class<T> clazz, long tag) {
- return new Extension<M, T>(type, clazz, (int) tag, false);
- }
-
/**
* Creates a repeated {@code Extension} of the given message type and tag number.
* Should be used by the generated code only.
@@ -110,8 +92,8 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
* @param type {@link #TYPE_MESSAGE} or {@link #TYPE_GROUP}
*/
public static <M extends ExtendableMessageNano<M>, T extends MessageNano>
- Extension<M, T[]> createRepeatedMessageTyped(int type, Class<T[]> clazz, long tag) {
- return new Extension<M, T[]>(type, clazz, (int) tag, true);
+ Extension<M, T[]> createRepeatedMessageTyped(int type, Class<T[]> clazz, int tag) {
+ return new Extension<M, T[]>(type, clazz, tag, true);
}
/**
@@ -122,8 +104,8 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
* @param clazz the boxed Java type of this extension
*/
public static <M extends ExtendableMessageNano<M>, T>
- Extension<M, T> createPrimitiveTyped(int type, Class<T> clazz, long tag) {
- return new PrimitiveExtension<M, T>(type, clazz, (int) tag, false, 0, 0);
+ Extension<M, T> createPrimitiveTyped(int type, Class<T> clazz, int tag) {
+ return new PrimitiveExtension<M, T>(type, clazz, tag, false, 0, 0);
}
/**
@@ -135,9 +117,8 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
*/
public static <M extends ExtendableMessageNano<M>, T>
Extension<M, T> createRepeatedPrimitiveTyped(
- int type, Class<T> clazz, long tag, long nonPackedTag, long packedTag) {
- return new PrimitiveExtension<M, T>(type, clazz, (int) tag, true,
- (int) nonPackedTag, (int) packedTag);
+ int type, Class<T> clazz, int tag, int nonPackedTag, int packedTag) {
+ return new PrimitiveExtension<M, T>(type, clazz, tag, true, nonPackedTag, packedTag);
}
/**
@@ -155,9 +136,9 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
protected final Class<T> clazz;
/**
- * Tag number of this extension. The data should be viewed as an unsigned 32-bit value.
+ * Tag number of this extension.
*/
- public final int tag;
+ protected final int tag;
/**
* Whether this extension is repeated.
diff --git a/java/src/main/java/com/google/protobuf/nano/FieldArray.java b/java/src/main/java/com/google/protobuf/nano/FieldArray.java
index 5e8856d..ab923a4 100644
--- a/java/src/main/java/com/google/protobuf/nano/FieldArray.java
+++ b/java/src/main/java/com/google/protobuf/nano/FieldArray.java
@@ -35,12 +35,9 @@ package com.google.protobuf.nano;
* A custom version of {@link android.util.SparseArray} with the minimal API
* for storing {@link FieldData} objects.
*
- * <p>This class is an internal implementation detail of nano and should not
- * be called directly by clients.
- *
* Based on {@link android.support.v4.util.SpareArrayCompat}.
*/
-public final class FieldArray implements Cloneable {
+class FieldArray {
private static final FieldData DELETED = new FieldData();
private boolean mGarbage = false;
@@ -51,7 +48,7 @@ public final class FieldArray implements Cloneable {
/**
* Creates a new FieldArray containing no fields.
*/
- FieldArray() {
+ public FieldArray() {
this(10);
}
@@ -60,7 +57,7 @@ public final class FieldArray implements Cloneable {
* require any additional memory allocation to store the specified
* number of mappings.
*/
- FieldArray(int initialCapacity) {
+ public FieldArray(int initialCapacity) {
initialCapacity = idealIntArraySize(initialCapacity);
mFieldNumbers = new int[initialCapacity];
mData = new FieldData[initialCapacity];
@@ -71,7 +68,7 @@ public final class FieldArray implements Cloneable {
* Gets the FieldData mapped from the specified fieldNumber, or <code>null</code>
* if no such mapping has been made.
*/
- FieldData get(int fieldNumber) {
+ public FieldData get(int fieldNumber) {
int i = binarySearch(fieldNumber);
if (i < 0 || mData[i] == DELETED) {
@@ -84,7 +81,7 @@ public final class FieldArray implements Cloneable {
/**
* Removes the data from the specified fieldNumber, if there was any.
*/
- void remove(int fieldNumber) {
+ public void remove(int fieldNumber) {
int i = binarySearch(fieldNumber);
if (i >= 0 && mData[i] != DELETED) {
@@ -121,7 +118,7 @@ public final class FieldArray implements Cloneable {
* Adds a mapping from the specified fieldNumber to the specified data,
* replacing the previous mapping if there was one.
*/
- void put(int fieldNumber, FieldData data) {
+ public void put(int fieldNumber, FieldData data) {
int i = binarySearch(fieldNumber);
if (i >= 0) {
@@ -170,7 +167,7 @@ public final class FieldArray implements Cloneable {
* Returns the number of key-value mappings that this FieldArray
* currently stores.
*/
- int size() {
+ public int size() {
if (mGarbage) {
gc();
}
@@ -187,7 +184,7 @@ public final class FieldArray implements Cloneable {
* the value from the <code>index</code>th key-value mapping that this
* FieldArray stores.
*/
- FieldData dataAt(int index) {
+ public FieldData dataAt(int index) {
if (mGarbage) {
gc();
}
@@ -273,19 +270,4 @@ public final class FieldArray implements Cloneable {
}
return true;
}
-
- @Override
- public final FieldArray clone() {
- // Trigger GC so we compact and don't copy DELETED elements.
- int size = size();
- FieldArray clone = new FieldArray(size);
- System.arraycopy(mFieldNumbers, 0, clone.mFieldNumbers, 0, size);
- for (int i = 0; i < size; i++) {
- if (mData[i] != null) {
- clone.mData[i] = mData[i].clone();
- }
- }
- clone.mSize = size;
- return clone;
- }
}
diff --git a/java/src/main/java/com/google/protobuf/nano/FieldData.java b/java/src/main/java/com/google/protobuf/nano/FieldData.java
index 20a5142..7a5eb4c 100644
--- a/java/src/main/java/com/google/protobuf/nano/FieldData.java
+++ b/java/src/main/java/com/google/protobuf/nano/FieldData.java
@@ -39,7 +39,7 @@ import java.util.List;
* Stores unknown fields. These might be extensions or fields that the generated API doesn't
* know about yet.
*/
-class FieldData implements Cloneable {
+class FieldData {
private Extension<?, ?> cachedExtension;
private Object value;
/** The serialised values for this object. Will be cleared if getValue is called */
@@ -58,23 +58,6 @@ class FieldData implements Cloneable {
unknownFieldData.add(unknownField);
}
- UnknownFieldData getUnknownField(int index) {
- if (unknownFieldData == null) {
- return null;
- }
- if (index < unknownFieldData.size()) {
- return unknownFieldData.get(index);
- }
- return null;
- }
-
- int getUnknownFieldSize() {
- if (unknownFieldData == null) {
- return 0;
- }
- return unknownFieldData.size();
- }
-
<T> T getValue(Extension<?, T> extension) {
if (value != null){
if (cachedExtension != extension) { // Extension objects are singletons.
@@ -187,54 +170,4 @@ class FieldData implements Cloneable {
return result;
}
- @Override
- public final FieldData clone() {
- FieldData clone = new FieldData();
- try {
- clone.cachedExtension = cachedExtension;
- if (unknownFieldData == null) {
- clone.unknownFieldData = null;
- } else {
- clone.unknownFieldData.addAll(unknownFieldData);
- }
-
- // Whether we need to deep clone value depends on its type. Primitive reference types
- // (e.g. Integer, Long etc.) are ok, since they're immutable. We need to clone arrays
- // and messages.
- if (value == null) {
- // No cloning required.
- } else if (value instanceof MessageNano) {
- clone.value = ((MessageNano) value).clone();
- } else if (value instanceof byte[]) {
- clone.value = ((byte[]) value).clone();
- } else if (value instanceof byte[][]) {
- byte[][] valueArray = (byte[][]) value;
- byte[][] cloneArray = new byte[valueArray.length][];
- clone.value = cloneArray;
- for (int i = 0; i < valueArray.length; i++) {
- cloneArray[i] = valueArray[i].clone();
- }
- } else if (value instanceof boolean[]) {
- clone.value = ((boolean[]) value).clone();
- } else if (value instanceof int[]) {
- clone.value = ((int[]) value).clone();
- } else if (value instanceof long[]) {
- clone.value = ((long[]) value).clone();
- } else if (value instanceof float[]) {
- clone.value = ((float[]) value).clone();
- } else if (value instanceof double[]) {
- clone.value = ((double[]) value).clone();
- } else if (value instanceof MessageNano[]) {
- MessageNano[] valueArray = (MessageNano[]) value;
- MessageNano[] cloneArray = new MessageNano[valueArray.length];
- clone.value = cloneArray;
- for (int i = 0; i < valueArray.length; i++) {
- cloneArray[i] = valueArray[i].clone();
- }
- }
- return clone;
- } catch (CloneNotSupportedException e) {
- throw new AssertionError(e);
- }
- }
}
diff --git a/java/src/main/java/com/google/protobuf/nano/InternalNano.java b/java/src/main/java/com/google/protobuf/nano/InternalNano.java
index c4adfa5..90ca11d 100644
--- a/java/src/main/java/com/google/protobuf/nano/InternalNano.java
+++ b/java/src/main/java/com/google/protobuf/nano/InternalNano.java
@@ -330,12 +330,4 @@ public final class InternalNano {
return result;
}
- // This avoids having to make FieldArray public.
- public static void cloneUnknownFieldData(ExtendableMessageNano original,
- ExtendableMessageNano cloned) {
- if (original.unknownFieldData != null) {
- cloned.unknownFieldData = (FieldArray) original.unknownFieldData.clone();
- }
- }
-
}
diff --git a/java/src/main/java/com/google/protobuf/nano/MessageNano.java b/java/src/main/java/com/google/protobuf/nano/MessageNano.java
index ea91b21..d6288c9 100644
--- a/java/src/main/java/com/google/protobuf/nano/MessageNano.java
+++ b/java/src/main/java/com/google/protobuf/nano/MessageNano.java
@@ -31,7 +31,6 @@
package com.google.protobuf.nano;
import java.io.IOException;
-import java.util.Arrays;
/**
* Abstract interface implemented by Protocol Message objects.
@@ -152,31 +151,6 @@ public abstract class MessageNano {
}
/**
- * Compares two {@code MessageNano}s and returns true if the message's are the same class and
- * have serialized form equality (i.e. all of the field values are the same).
- */
- public static final boolean messageNanoEquals(MessageNano a, MessageNano b) {
- if (a == b) {
- return true;
- }
- if (a == null || b == null) {
- return false;
- }
- if (a.getClass() != b.getClass()) {
- return false;
- }
- final int serializedSize = a.getSerializedSize();
- if (b.getSerializedSize() != serializedSize) {
- return false;
- }
- final byte[] aByteArray = new byte[serializedSize];
- final byte[] bByteArray = new byte[serializedSize];
- toByteArray(a, aByteArray, 0, serializedSize);
- toByteArray(b, bByteArray, 0, serializedSize);
- return Arrays.equals(aByteArray, bByteArray);
- }
-
- /**
* Returns a string that is (mostly) compatible with ProtoBuffer's TextFormat. Note that groups
* (which are deprecated) are not serialized with the correct field name.
*
@@ -187,12 +161,4 @@ public abstract class MessageNano {
public String toString() {
return MessageNanoPrinter.print(this);
}
-
- /**
- * Provides support for cloning. This only works if you specify the generate_clone method.
- */
- @Override
- public MessageNano clone() throws CloneNotSupportedException {
- return (MessageNano) super.clone();
- }
}
diff --git a/java/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java b/java/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java
index a30f2f3..572a707 100644
--- a/java/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java
+++ b/java/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java
@@ -108,10 +108,6 @@ public final class MessageNanoPrinter {
for (Field field : clazz.getFields()) {
int modifiers = field.getModifiers();
String fieldName = field.getName();
- if ("cachedSize".equals(fieldName)) {
- // TODO(bduff): perhaps cachedSize should have a more obscure name.
- continue;
- }
if ((modifiers & Modifier.PUBLIC) == Modifier.PUBLIC
&& (modifiers & Modifier.STATIC) != Modifier.STATIC
@@ -247,7 +243,7 @@ public final class MessageNanoPrinter {
builder.append('"');
for (int i = 0; i < bytes.length; ++i) {
- int ch = bytes[i] & 0xff;
+ int ch = bytes[i];
if (ch == '\\' || ch == '"') {
builder.append('\\').append((char) ch);
} else if (ch >= 32 && ch < 127) {
diff --git a/java/src/main/java/com/google/protobuf/nano/UnknownFieldData.java b/java/src/main/java/com/google/protobuf/nano/UnknownFieldData.java
index bf34bed..2032e1a 100644
--- a/java/src/main/java/com/google/protobuf/nano/UnknownFieldData.java
+++ b/java/src/main/java/com/google/protobuf/nano/UnknownFieldData.java
@@ -42,10 +42,6 @@ import java.util.Arrays;
final class UnknownFieldData {
final int tag;
- /**
- * Important: this should be treated as immutable, even though it's possible
- * to change the array values.
- */
final byte[] bytes;
UnknownFieldData(int tag, byte[] bytes) {
diff --git a/java/src/main/java/com/google/protobuf/nano/WireFormatNano.java b/java/src/main/java/com/google/protobuf/nano/WireFormatNano.java
index a3405e5..1ff8f06 100644
--- a/java/src/main/java/com/google/protobuf/nano/WireFormatNano.java
+++ b/java/src/main/java/com/google/protobuf/nano/WireFormatNano.java
@@ -113,7 +113,11 @@ public final class WireFormatNano {
int arrayLength = 1;
int startPos = input.getPosition();
input.skipField(tag);
- while (input.readTag() == tag) {
+ while (input.getBytesUntilLimit() > 0) {
+ int thisTag = input.readTag();
+ if (thisTag != tag) {
+ break;
+ }
input.skipField(tag);
arrayLength++;
}