diff options
Diffstat (limited to 'java/core/src/main/java/com/google/protobuf')
19 files changed, 260 insertions, 191 deletions
diff --git a/java/core/src/main/java/com/google/protobuf/AbstractMessage.java b/java/core/src/main/java/com/google/protobuf/AbstractMessage.java index fc3c2a5d..09aaed18 100644 --- a/java/core/src/main/java/com/google/protobuf/AbstractMessage.java +++ b/java/core/src/main/java/com/google/protobuf/AbstractMessage.java @@ -32,7 +32,6 @@ package com.google.protobuf; import com.google.protobuf.Descriptors.EnumValueDescriptor; import com.google.protobuf.Descriptors.FieldDescriptor; -import com.google.protobuf.Descriptors.FileDescriptor.Syntax; import com.google.protobuf.Descriptors.OneofDescriptor; import com.google.protobuf.Internal.EnumLite; import java.io.IOException; @@ -446,10 +445,7 @@ public abstract class AbstractMessage final CodedInputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException { - boolean discardUnknown = - getDescriptorForType().getFile().getSyntax() == Syntax.PROTO3 - ? input.shouldDiscardUnknownFieldsProto3() - : input.shouldDiscardUnknownFields(); + boolean discardUnknown = input.shouldDiscardUnknownFields(); final UnknownFieldSet.Builder unknownFields = discardUnknown ? null : UnknownFieldSet.newBuilder(getUnknownFields()); while (true) { diff --git a/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java b/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java index 4d7a9727..0dedb173 100644 --- a/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java @@ -42,7 +42,8 @@ import java.util.RandomAccess; * * @author dweis@google.com (Daniel Weis) */ -final class BooleanArrayList extends AbstractProtobufList<Boolean> +final class BooleanArrayList + extends AbstractProtobufList<Boolean> implements BooleanList, RandomAccess, PrimitiveNonBoxingCollection { private static final BooleanArrayList EMPTY_LIST = new BooleanArrayList(); diff --git a/java/core/src/main/java/com/google/protobuf/ByteString.java b/java/core/src/main/java/com/google/protobuf/ByteString.java index d67bb54a..ddda0f26 100644 --- a/java/core/src/main/java/com/google/protobuf/ByteString.java +++ b/java/core/src/main/java/com/google/protobuf/ByteString.java @@ -46,6 +46,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; @@ -222,6 +223,67 @@ public abstract class ByteString implements Iterable<Byte>, Serializable { } // ================================================================= + // Comparison + + private static final int UNSIGNED_BYTE_MASK = 0xFF; + + /** + * Returns the value of the given byte as an integer, interpreting the byte as an unsigned value. + * That is, returns {@code value + 256} if {@code value} is negative; {@code value} itself + * otherwise. + * + * <p>Note: This code was copied from {@link com.google.common.primitives.UnsignedBytes#toInt}, as + * Guava libraries cannot be used in the {@code com.google.protobuf} package. + */ + private static int toInt(byte value) { + return value & UNSIGNED_BYTE_MASK; + } + + /** + * Compares two {@link ByteString}s lexicographically, treating their contents as unsigned byte + * values between 0 and 255 (inclusive). + * + * <p>For example, {@code (byte) -1} is considered to be greater than {@code (byte) 1} because + * it is interpreted as an unsigned value, {@code 255}. + */ + private static final Comparator<ByteString> UNSIGNED_LEXICOGRAPHICAL_COMPARATOR = + new Comparator<ByteString>() { + @Override + public int compare(ByteString former, ByteString latter) { + ByteIterator formerBytes = former.iterator(); + ByteIterator latterBytes = latter.iterator(); + + while (formerBytes.hasNext() && latterBytes.hasNext()) { + // Note: This code was copied from com.google.common.primitives.UnsignedBytes#compare, + // as Guava libraries cannot be used in the {@code com.google.protobuf} package. + int result = + Integer.compare(toInt(formerBytes.nextByte()), toInt(latterBytes.nextByte())); + if (result != 0) { + return result; + } + } + + return Integer.compare(former.size(), latter.size()); + } + }; + + /** + * Returns a {@link Comparator<ByteString>} which compares {@link ByteString}-s lexicographically + * as sequences of unsigned bytes (i.e. values between 0 and 255, inclusive). + * + * <p>For example, {@code (byte) -1} is considered to be greater than {@code (byte) 1} because + * it is interpreted as an unsigned value, {@code 255}: + * + * <ul> + * <li>{@code `-1` -> 0b11111111 (two's complement) -> 255} + * <li>{@code `1` -> 0b00000001 -> 1} + * </ul> + */ + public static Comparator<ByteString> unsignedLexicographicalComparator() { + return UNSIGNED_LEXICOGRAPHICAL_COMPARATOR; + } + + // ================================================================= // ByteString -> substring /** @@ -287,8 +349,10 @@ public abstract class ByteString implements Iterable<Byte>, Serializable { * @param offset offset in source array * @param size number of bytes to copy * @return new {@code ByteString} + * @throws IndexOutOfBoundsException if {@code offset} or {@code size} are out of bounds */ public static ByteString copyFrom(byte[] bytes, int offset, int size) { + checkRange(offset, offset + size, bytes.length); return new LiteralByteString(byteArrayCopier.copyFrom(bytes, offset, size)); } @@ -339,8 +403,10 @@ public abstract class ByteString implements Iterable<Byte>, Serializable { * @param bytes source buffer * @param size number of bytes to copy * @return new {@code ByteString} + * @throws IndexOutOfBoundsException if {@code size > bytes.remaining()} */ public static ByteString copyFrom(ByteBuffer bytes, int size) { + checkRange(0, size, bytes.remaining()); byte[] copy = new byte[size]; bytes.get(copy); return new LiteralByteString(copy); @@ -578,6 +644,9 @@ public abstract class ByteString implements Iterable<Byte>, Serializable { /** * Copies bytes into a buffer at the given offset. * + * <p>To copy a subset of bytes, you call this method on the return value of {@link + * #substring(int, int)}. Example: {@code byteString.substring(start, end).copyTo(target, offset)} + * * @param target buffer to copy into * @param offset in the target buffer * @throws IndexOutOfBoundsException if the offset is negative or too large @@ -589,15 +658,16 @@ public abstract class ByteString implements Iterable<Byte>, Serializable { /** * Copies bytes into a buffer. * - * @param target buffer to copy into + * @param target buffer to copy into * @param sourceOffset offset within these bytes * @param targetOffset offset within the target buffer * @param numberToCopy number of bytes to copy - * @throws IndexOutOfBoundsException if an offset or size is negative or too - * large + * @throws IndexOutOfBoundsException if an offset or size is negative or too large + * @deprecation Instead, call {@code byteString.substring(sourceOffset, sourceOffset + + * numberToCopy).copyTo(target, targetOffset)} */ - public final void copyTo(byte[] target, int sourceOffset, int targetOffset, - int numberToCopy) { + @Deprecated + public final void copyTo(byte[] target, int sourceOffset, int targetOffset, int numberToCopy) { checkRange(sourceOffset, sourceOffset + numberToCopy, size()); checkRange(targetOffset, targetOffset + numberToCopy, target.length); if (numberToCopy > 0) { @@ -617,10 +687,13 @@ public abstract class ByteString implements Iterable<Byte>, Serializable { /** * Copies bytes into a ByteBuffer. * + * <p>To copy a subset of bytes, you call this method on the return value of {@link + * #substring(int, int)}. Example: {@code byteString.substring(start, end).copyTo(target)} + * * @param target ByteBuffer to copy into. * @throws java.nio.ReadOnlyBufferException if the {@code target} is read-only - * @throws java.nio.BufferOverflowException if the {@code target}'s - * remaining() space is not large enough to hold the data. + * @throws java.nio.BufferOverflowException if the {@code target}'s remaining() space is not large + * enough to hold the data. */ public abstract void copyTo(ByteBuffer target); @@ -1258,6 +1331,9 @@ public abstract class ByteString implements Iterable<Byte>, Serializable { * @param bytes array to wrap */ LiteralByteString(byte[] bytes) { + if (bytes == null) { + throw new NullPointerException(); + } this.bytes = bytes; } diff --git a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java index 1297462e..4545d0ae 100644 --- a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java +++ b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java @@ -64,12 +64,6 @@ public abstract class CodedInputStream { // Integer.MAX_VALUE == 0x7FFFFFF == INT_MAX from limits.h private static final int DEFAULT_SIZE_LIMIT = Integer.MAX_VALUE; - /** - * Whether to enable our custom UTF-8 decode codepath which does not use {@link StringCoding}. - * Currently disabled. - */ - private static final boolean ENABLE_CUSTOM_UTF8_DECODE = false; - /** Visible for subclasses. See setRecursionLimit() */ int recursionDepth; @@ -417,21 +411,7 @@ public abstract class CodedInputStream { } - private boolean explicitDiscardUnknownFields = false; - - private static volatile boolean proto3DiscardUnknownFieldsDefault = false; - - static void setProto3DiscardUnknownsByDefaultForTest() { - proto3DiscardUnknownFieldsDefault = true; - } - - static void setProto3KeepUnknownsByDefaultForTest() { - proto3DiscardUnknownFieldsDefault = false; - } - - static boolean getProto3DiscardUnknownFieldsDefault() { - return proto3DiscardUnknownFieldsDefault; - } + private boolean shouldDiscardUnknownFields = false; /** * Sets this {@code CodedInputStream} to discard unknown fields. Only applies to full runtime @@ -442,7 +422,7 @@ public abstract class CodedInputStream { * runtime. */ final void discardUnknownFields() { - explicitDiscardUnknownFields = true; + shouldDiscardUnknownFields = true; } /** @@ -450,7 +430,7 @@ public abstract class CodedInputStream { * default. */ final void unsetDiscardUnknownFields() { - explicitDiscardUnknownFields = false; + shouldDiscardUnknownFields = false; } /** @@ -458,19 +438,7 @@ public abstract class CodedInputStream { * runtime messages. */ final boolean shouldDiscardUnknownFields() { - return explicitDiscardUnknownFields; - } - - /** - * Whether unknown fields in this input stream should be discarded during parsing for proto3 full - * runtime messages. - * - * <p>This function was temporarily introduced before proto3 unknown fields behavior is changed. - * TODO(liujisi): remove this and related code in GeneratedMessage after proto3 unknown - * fields migration is done. - */ - final boolean shouldDiscardUnknownFieldsProto3() { - return explicitDiscardUnknownFields ? true : proto3DiscardUnknownFieldsDefault; + return shouldDiscardUnknownFields; } /** @@ -831,19 +799,9 @@ public abstract class CodedInputStream { public String readStringRequireUtf8() throws IOException { final int size = readRawVarint32(); if (size > 0 && size <= (limit - pos)) { - if (ENABLE_CUSTOM_UTF8_DECODE) { - String result = Utf8.decodeUtf8(buffer, pos, size); - pos += size; - return result; - } else { - // TODO(martinrb): We could save a pass by validating while decoding. - if (!Utf8.isValidUtf8(buffer, pos, pos + size)) { - throw InvalidProtocolBufferException.invalidUtf8(); - } - final int tempPos = pos; - pos += size; - return new String(buffer, tempPos, size, UTF_8); - } + String result = Utf8.decodeUtf8(buffer, pos, size); + pos += size; + return result; } if (size == 0) { @@ -1559,25 +1517,10 @@ public abstract class CodedInputStream { public String readStringRequireUtf8() throws IOException { final int size = readRawVarint32(); if (size > 0 && size <= remaining()) { - if (ENABLE_CUSTOM_UTF8_DECODE) { - final int bufferPos = bufferPos(pos); - String result = Utf8.decodeUtf8(buffer, bufferPos, size); - pos += size; - return result; - } else { - // TODO(nathanmittler): Is there a way to avoid this copy? - // The same as readBytes' logic - byte[] bytes = new byte[size]; - UnsafeUtil.copyMemory(pos, bytes, 0, size); - // TODO(martinrb): We could save a pass by validating while decoding. - if (!Utf8.isValidUtf8(bytes)) { - throw InvalidProtocolBufferException.invalidUtf8(); - } - - String result = new String(bytes, UTF_8); - pos += size; - return result; - } + final int bufferPos = bufferPos(pos); + String result = Utf8.decodeUtf8(buffer, bufferPos, size); + pos += size; + return result; } if (size == 0) { @@ -2345,15 +2288,7 @@ public abstract class CodedInputStream { bytes = readRawBytesSlowPath(size); tempPos = 0; } - if (ENABLE_CUSTOM_UTF8_DECODE) { - return Utf8.decodeUtf8(bytes, tempPos, size); - } else { - // TODO(martinrb): We could save a pass by validating while decoding. - if (!Utf8.isValidUtf8(bytes, tempPos, tempPos + size)) { - throw InvalidProtocolBufferException.invalidUtf8(); - } - return new String(bytes, tempPos, size, UTF_8); - } + return Utf8.decodeUtf8(bytes, tempPos, size); } @Override @@ -3373,34 +3308,15 @@ public abstract class CodedInputStream { public String readStringRequireUtf8() throws IOException { final int size = readRawVarint32(); if (size > 0 && size <= currentByteBufferLimit - currentByteBufferPos) { - if (ENABLE_CUSTOM_UTF8_DECODE) { - final int bufferPos = (int) (currentByteBufferPos - currentByteBufferStartPos); - String result = Utf8.decodeUtf8(currentByteBuffer, bufferPos, size); - currentByteBufferPos += size; - return result; - } else { - byte[] bytes = new byte[size]; - UnsafeUtil.copyMemory(currentByteBufferPos, bytes, 0, size); - if (!Utf8.isValidUtf8(bytes)) { - throw InvalidProtocolBufferException.invalidUtf8(); - } - String result = new String(bytes, UTF_8); - currentByteBufferPos += size; - return result; - } + final int bufferPos = (int) (currentByteBufferPos - currentByteBufferStartPos); + String result = Utf8.decodeUtf8(currentByteBuffer, bufferPos, size); + currentByteBufferPos += size; + return result; } if (size >= 0 && size <= remaining()) { byte[] bytes = new byte[size]; readRawBytesTo(bytes, 0, size); - if (ENABLE_CUSTOM_UTF8_DECODE) { - return Utf8.decodeUtf8(bytes, 0, size); - } else { - if (!Utf8.isValidUtf8(bytes)) { - throw InvalidProtocolBufferException.invalidUtf8(); - } - String result = new String(bytes, UTF_8); - return result; - } + return Utf8.decodeUtf8(bytes, 0, size); } if (size == 0) { diff --git a/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java b/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java index 5b28b4a8..8d987b2e 100644 --- a/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java @@ -42,7 +42,8 @@ import java.util.RandomAccess; * * @author dweis@google.com (Daniel Weis) */ -final class DoubleArrayList extends AbstractProtobufList<Double> +final class DoubleArrayList + extends AbstractProtobufList<Double> implements DoubleList, RandomAccess, PrimitiveNonBoxingCollection { private static final DoubleArrayList EMPTY_LIST = new DoubleArrayList(); diff --git a/java/core/src/main/java/com/google/protobuf/DynamicMessage.java b/java/core/src/main/java/com/google/protobuf/DynamicMessage.java index a6a774b7..2c346e03 100644 --- a/java/core/src/main/java/com/google/protobuf/DynamicMessage.java +++ b/java/core/src/main/java/com/google/protobuf/DynamicMessage.java @@ -608,20 +608,12 @@ public final class DynamicMessage extends AbstractMessage { @Override public Builder setUnknownFields(UnknownFieldSet unknownFields) { - if (getDescriptorForType().getFile().getSyntax() == Descriptors.FileDescriptor.Syntax.PROTO3 - && CodedInputStream.getProto3DiscardUnknownFieldsDefault()) { - return this; - } this.unknownFields = unknownFields; return this; } @Override public Builder mergeUnknownFields(UnknownFieldSet unknownFields) { - if (getDescriptorForType().getFile().getSyntax() == Descriptors.FileDescriptor.Syntax.PROTO3 - && CodedInputStream.getProto3DiscardUnknownFieldsDefault()) { - return this; - } this.unknownFields = UnknownFieldSet.newBuilder(this.unknownFields) .mergeFrom(unknownFields) diff --git a/java/core/src/main/java/com/google/protobuf/FloatArrayList.java b/java/core/src/main/java/com/google/protobuf/FloatArrayList.java index 7c080af3..41749f6d 100644 --- a/java/core/src/main/java/com/google/protobuf/FloatArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/FloatArrayList.java @@ -42,7 +42,8 @@ import java.util.RandomAccess; * * @author dweis@google.com (Daniel Weis) */ -final class FloatArrayList extends AbstractProtobufList<Float> +final class FloatArrayList + extends AbstractProtobufList<Float> implements FloatList, RandomAccess, PrimitiveNonBoxingCollection { private static final FloatArrayList EMPTY_LIST = new FloatArrayList(); diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java index 1e122d16..ff670fd8 100644 --- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java +++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java @@ -33,7 +33,6 @@ package com.google.protobuf; import com.google.protobuf.AbstractMessageLite.Builder.LimitedInputStream; import com.google.protobuf.Internal.BooleanList; import com.google.protobuf.Internal.DoubleList; -import com.google.protobuf.Internal.EnumLiteMap; import com.google.protobuf.Internal.FloatList; import com.google.protobuf.Internal.IntList; import com.google.protobuf.Internal.LongList; @@ -1608,7 +1607,7 @@ public abstract class GeneratedMessageLite< protected static class DefaultInstanceBasedParser<T extends GeneratedMessageLite<T, ?>> extends AbstractParser<T> { - private T defaultInstance; + private final T defaultInstance; public DefaultInstanceBasedParser(T defaultInstance) { this.defaultInstance = defaultInstance; diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java index 4acd8f2f..53af544f 100644 --- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java +++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java @@ -38,6 +38,11 @@ import com.google.protobuf.Descriptors.EnumValueDescriptor; import com.google.protobuf.Descriptors.FieldDescriptor; import com.google.protobuf.Descriptors.FileDescriptor; import com.google.protobuf.Descriptors.OneofDescriptor; +import com.google.protobuf.Internal.BooleanList; +import com.google.protobuf.Internal.DoubleList; +import com.google.protobuf.Internal.FloatList; +import com.google.protobuf.Internal.IntList; +import com.google.protobuf.Internal.LongList; // In opensource protobuf, we have versioned this GeneratedMessageV3 class to GeneratedMessageV3V3 and // in the future may have GeneratedMessageV3V4 etc. This allows us to change some aspects of this // class without breaking binary compatibility with old generated code that still subclasses @@ -293,16 +298,17 @@ public abstract class GeneratedMessageV3 extends AbstractMessage return unknownFields.mergeFieldFrom(tag, input); } + /** + * Delegates to parseUnknownField. This method is obsolete, but we must retain it for + * compatibility with older generated code. + */ protected boolean parseUnknownFieldProto3( CodedInputStream input, UnknownFieldSet.Builder unknownFields, ExtensionRegistryLite extensionRegistry, int tag) throws IOException { - if (input.shouldDiscardUnknownFieldsProto3()) { - return input.skipField(tag); - } - return unknownFields.mergeFieldFrom(tag, input); + return parseUnknownField(input, unknownFields, extensionRegistry, tag); } protected static <M extends Message> M parseWithIOException(Parser<M> parser, InputStream input) @@ -363,6 +369,76 @@ public abstract class GeneratedMessageV3 extends AbstractMessage return UnsafeUtil.hasUnsafeArrayOperations() && UnsafeUtil.hasUnsafeByteBufferOperations(); } + protected static IntList emptyIntList() { + return IntArrayList.emptyList(); + } + + protected static IntList newIntList() { + return new IntArrayList(); + } + + protected static IntList mutableCopy(IntList list) { + int size = list.size(); + return list.mutableCopyWithCapacity( + size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); + } + + protected static LongList emptyLongList() { + return LongArrayList.emptyList(); + } + + protected static LongList newLongList() { + return new LongArrayList(); + } + + protected static LongList mutableCopy(LongList list) { + int size = list.size(); + return list.mutableCopyWithCapacity( + size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); + } + + protected static FloatList emptyFloatList() { + return FloatArrayList.emptyList(); + } + + protected static FloatList newFloatList() { + return new FloatArrayList(); + } + + protected static FloatList mutableCopy(FloatList list) { + int size = list.size(); + return list.mutableCopyWithCapacity( + size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); + } + + protected static DoubleList emptyDoubleList() { + return DoubleArrayList.emptyList(); + } + + protected static DoubleList newDoubleList() { + return new DoubleArrayList(); + } + + protected static DoubleList mutableCopy(DoubleList list) { + int size = list.size(); + return list.mutableCopyWithCapacity( + size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); + } + + protected static BooleanList emptyBooleanList() { + return BooleanArrayList.emptyList(); + } + + protected static BooleanList newBooleanList() { + return new BooleanArrayList(); + } + + protected static BooleanList mutableCopy(BooleanList list) { + int size = list.size(); + return list.mutableCopyWithCapacity( + size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); + } + @Override public void writeTo(final CodedOutputStream output) throws IOException { MessageReflection.writeMessageTo(this, getAllFieldsRaw(), output, false); @@ -641,13 +717,12 @@ public abstract class GeneratedMessageV3 extends AbstractMessage return (BuilderType) this; } + /** + * Delegates to setUnknownFields. This method is obsolete, but we must retain it for + * compatibility with older generated code. + */ protected BuilderType setUnknownFieldsProto3(final UnknownFieldSet unknownFields) { - if (CodedInputStream.getProto3DiscardUnknownFieldsDefault()) { - return (BuilderType) this; - } - this.unknownFields = unknownFields; - onChanged(); - return (BuilderType) this; + return setUnknownFields(unknownFields); } @Override @@ -1009,19 +1084,17 @@ public abstract class GeneratedMessageV3 extends AbstractMessage getDescriptorForType(), new MessageReflection.ExtensionAdapter(extensions), tag); } + /** + * Delegates to parseUnknownField. This method is obsolete, but we must retain it for + * compatibility with older generated code. + */ @Override protected boolean parseUnknownFieldProto3( CodedInputStream input, UnknownFieldSet.Builder unknownFields, ExtensionRegistryLite extensionRegistry, int tag) throws IOException { - return MessageReflection.mergeFieldFrom( - input, - input.shouldDiscardUnknownFieldsProto3() ? null : unknownFields, - extensionRegistry, - getDescriptorForType(), - new MessageReflection.ExtensionAdapter(extensions), - tag); + return parseUnknownField(input, unknownFields, extensionRegistry, tag); } diff --git a/java/core/src/main/java/com/google/protobuf/IntArrayList.java b/java/core/src/main/java/com/google/protobuf/IntArrayList.java index aacd71e1..4993eea7 100644 --- a/java/core/src/main/java/com/google/protobuf/IntArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/IntArrayList.java @@ -42,7 +42,8 @@ import java.util.RandomAccess; * * @author dweis@google.com (Daniel Weis) */ -final class IntArrayList extends AbstractProtobufList<Integer> +final class IntArrayList + extends AbstractProtobufList<Integer> implements IntList, RandomAccess, PrimitiveNonBoxingCollection { private static final IntArrayList EMPTY_LIST = new IntArrayList(); diff --git a/java/core/src/main/java/com/google/protobuf/Internal.java b/java/core/src/main/java/com/google/protobuf/Internal.java index 848cad03..878573d5 100644 --- a/java/core/src/main/java/com/google/protobuf/Internal.java +++ b/java/core/src/main/java/com/google/protobuf/Internal.java @@ -234,6 +234,11 @@ public final class Internal { T findValueByNumber(int number); } + /** Interface for an object which verifies integers are in range. */ + public interface EnumVerifier { + boolean isInRange(int number); + } + /** * Helper method for implementing {@link Message#hashCode()} for longs. * @see Long#hashCode() diff --git a/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java b/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java index d474c51e..6cfc14a5 100644 --- a/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java @@ -69,7 +69,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String> static { EMPTY_LIST.makeImmutable(); } - + static LazyStringArrayList emptyList() { return EMPTY_LIST; } @@ -83,8 +83,8 @@ public class LazyStringArrayList extends AbstractProtobufList<String> this(DEFAULT_CAPACITY); } - public LazyStringArrayList(int intialCapacity) { - this(new ArrayList<Object>(intialCapacity)); + public LazyStringArrayList(int initialCapacity) { + this(new ArrayList<Object>(initialCapacity)); } public LazyStringArrayList(LazyStringList from) { @@ -95,7 +95,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String> public LazyStringArrayList(List<String> from) { this(new ArrayList<Object>(from)); } - + private LazyStringArrayList(ArrayList<Object> list) { this.list = list; } @@ -150,13 +150,13 @@ public class LazyStringArrayList extends AbstractProtobufList<String> list.add(index, element); modCount++; } - + private void add(int index, ByteString element) { ensureIsMutable(); list.add(index, element); modCount++; } - + private void add(int index, byte[] element) { ensureIsMutable(); list.add(index, element); @@ -221,7 +221,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String> list.add(element); modCount++; } - + @Override public void add(byte[] element) { ensureIsMutable(); @@ -233,7 +233,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String> public Object getRaw(int index) { return list.get(index); } - + @Override public ByteString getByteString(int index) { Object o = list.get(index); @@ -243,7 +243,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String> } return b; } - + @Override public byte[] getByteArray(int index) { Object o = list.get(index); @@ -258,7 +258,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String> public void set(int index, ByteString s) { setAndReturn(index, s); } - + private Object setAndReturn(int index, ByteString s) { ensureIsMutable(); return list.set(index, s); @@ -268,7 +268,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String> public void set(int index, byte[] s) { setAndReturn(index, s); } - + private Object setAndReturn(int index, byte[] s) { ensureIsMutable(); return list.set(index, s); @@ -283,7 +283,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String> return Internal.toStringUtf8((byte[]) o); } } - + private static ByteString asByteString(Object o) { if (o instanceof ByteString) { return (ByteString) o; @@ -293,7 +293,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String> return ByteString.copyFrom((byte[]) o); } } - + private static byte[] asByteArray(Object o) { if (o instanceof byte[]) { return (byte[]) o; @@ -327,11 +327,11 @@ public class LazyStringArrayList extends AbstractProtobufList<String> private static class ByteArrayListView extends AbstractList<byte[]> implements RandomAccess { private final LazyStringArrayList list; - + ByteArrayListView(LazyStringArrayList list) { this.list = list; } - + @Override public byte[] get(int index) { return list.getByteArray(index); @@ -362,7 +362,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String> return asByteArray(o); } } - + @Override public List<byte[]> asByteArrayList() { return new ByteArrayListView(this); diff --git a/java/core/src/main/java/com/google/protobuf/LongArrayList.java b/java/core/src/main/java/com/google/protobuf/LongArrayList.java index 95945cb7..9a5056be 100644 --- a/java/core/src/main/java/com/google/protobuf/LongArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/LongArrayList.java @@ -42,7 +42,8 @@ import java.util.RandomAccess; * * @author dweis@google.com (Daniel Weis) */ -final class LongArrayList extends AbstractProtobufList<Long> +final class LongArrayList + extends AbstractProtobufList<Long> implements LongList, RandomAccess, PrimitiveNonBoxingCollection { private static final LongArrayList EMPTY_LIST = new LongArrayList(); diff --git a/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java b/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java index 29f567dc..b593b566 100644 --- a/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java +++ b/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java @@ -30,6 +30,8 @@ package com.google.protobuf; +import static com.google.protobuf.Internal.checkNotNull; + import java.util.AbstractList; import java.util.ArrayList; import java.util.Collection; @@ -290,9 +292,7 @@ public class RepeatedFieldBuilder */ public RepeatedFieldBuilder<MType, BType, IType> setMessage( int index, MType message) { - if (message == null) { - throw new NullPointerException(); - } + checkNotNull(message); ensureMutableMessageList(); messages.set(index, message); if (builders != null) { @@ -315,9 +315,7 @@ public class RepeatedFieldBuilder */ public RepeatedFieldBuilder<MType, BType, IType> addMessage( MType message) { - if (message == null) { - throw new NullPointerException(); - } + checkNotNull(message); ensureMutableMessageList(); messages.add(message); if (builders != null) { @@ -339,9 +337,7 @@ public class RepeatedFieldBuilder */ public RepeatedFieldBuilder<MType, BType, IType> addMessage( int index, MType message) { - if (message == null) { - throw new NullPointerException(); - } + checkNotNull(message); ensureMutableMessageList(); messages.add(index, message); if (builders != null) { @@ -363,9 +359,7 @@ public class RepeatedFieldBuilder public RepeatedFieldBuilder<MType, BType, IType> addAllMessages( Iterable<? extends MType> values) { for (final MType value : values) { - if (value == null) { - throw new NullPointerException(); - } + checkNotNull(value); } // If we can inspect the size, we can more efficiently add messages. diff --git a/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java b/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java index 941b5def..1f5ec8a2 100644 --- a/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java +++ b/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java @@ -30,6 +30,8 @@ package com.google.protobuf; +import static com.google.protobuf.Internal.checkNotNull; + /** * {@code SingleFieldBuilder} implements a structure that a protocol * message uses to hold a single field of another protocol message. It supports @@ -84,10 +86,7 @@ public class SingleFieldBuilder MType message, GeneratedMessage.BuilderParent parent, boolean isClean) { - if (message == null) { - throw new NullPointerException(); - } - this.message = message; + this.message = checkNotNull(message); this.parent = parent; this.isClean = isClean; } @@ -169,10 +168,7 @@ public class SingleFieldBuilder */ public SingleFieldBuilder<MType, BType, IType> setMessage( MType message) { - if (message == null) { - throw new NullPointerException(); - } - this.message = message; + this.message = checkNotNull(message); if (builder != null) { builder.dispose(); builder = null; diff --git a/java/core/src/main/java/com/google/protobuf/TextFormat.java b/java/core/src/main/java/com/google/protobuf/TextFormat.java index 25c3474f..79962e08 100644 --- a/java/core/src/main/java/com/google/protobuf/TextFormat.java +++ b/java/core/src/main/java/com/google/protobuf/TextFormat.java @@ -1444,8 +1444,8 @@ public final class TextFormat { logger.warning(msg.toString()); } else { String[] lineColumn = unknownFields.get(0).split(":"); - throw new ParseException(Integer.valueOf(lineColumn[0]), - Integer.valueOf(lineColumn[1]), msg.toString()); + throw new ParseException( + Integer.parseInt(lineColumn[0]), Integer.parseInt(lineColumn[1]), msg.toString()); } } diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java index 37d64633..b3fdebcb 100644 --- a/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java +++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java @@ -786,6 +786,23 @@ public final class UnknownFieldSet implements MessageLite { } /** + * Serializes the message to a {@code ByteString} and returns it. This is just a trivial wrapper + * around {@link #writeTo(int, CodedOutputStream)}. + */ + public ByteString toByteString(int fieldNumber) { + try { + // TODO(lukes): consider caching serialized size in a volatile long + final ByteString.CodedBuilder out = + ByteString.newCodedBuilder(getSerializedSize(fieldNumber)); + writeTo(fieldNumber, out.getCodedOutput()); + return out.build(); + } catch (IOException e) { + throw new RuntimeException( + "Serializing to a ByteString should never fail with an IOException", e); + } + } + + /** * Serializes the field, including field number, and writes it to * {@code output}. */ diff --git a/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java b/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java index d84ef3c5..f822ce51 100644 --- a/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java +++ b/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java @@ -33,6 +33,7 @@ package com.google.protobuf; import java.lang.reflect.Field; import java.nio.Buffer; import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.security.AccessController; import java.security.PrivilegedExceptionAction; import java.util.logging.Level; @@ -146,6 +147,10 @@ final class UnsafeUtil { return MEMORY_ACCESSOR.getObject(target, offset); } + static void putObject(Object target, long offset, Object value) { + MEMORY_ACCESSOR.putObject(target, offset, value); + } + static byte getByte(byte[] target, long index) { return MEMORY_ACCESSOR.getByte(target, BYTE_ARRAY_BASE_OFFSET + index); } @@ -370,12 +375,6 @@ final class UnsafeUtil { return field != null && field.getType() == long.class ? field : null; } - /** Finds the value field within a {@link String}. */ - private static Field stringValueField() { - Field field = field(String.class, "value"); - return field != null && field.getType() == char[].class ? field : null; - } - /** * Returns the offset of the provided field, or {@code -1} if {@code sun.misc.Unsafe} is not * available. diff --git a/java/core/src/main/java/com/google/protobuf/Utf8.java b/java/core/src/main/java/com/google/protobuf/Utf8.java index de75fe6b..b4a81ca3 100644 --- a/java/core/src/main/java/com/google/protobuf/Utf8.java +++ b/java/core/src/main/java/com/google/protobuf/Utf8.java @@ -42,7 +42,6 @@ import static java.lang.Character.isSurrogatePair; import static java.lang.Character.toCodePoint; import java.nio.ByteBuffer; -import java.util.Arrays; /** * A set of low-level, high-performance static utility methods related @@ -87,7 +86,9 @@ final class Utf8 { * delegate for which all methods are delegated directly to. */ private static final Processor processor = - UnsafeProcessor.isAvailable() ? new UnsafeProcessor() : new SafeProcessor(); + (UnsafeProcessor.isAvailable() && !Android.isOnAndroidDevice()) + ? new UnsafeProcessor() + : new SafeProcessor(); /** * A mask used when performing unsafe reads to determine if a long value contains any non-ASCII |