diff options
Diffstat (limited to 'java/src/main/java/com/google/protobuf/nano')
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++; } |