Commit b55a20fa authored by xiaofeng@google.com's avatar xiaofeng@google.com

Down-integrate from internal branch

parent 9ced30ca
2012-09-19 version 2.5.0:
General
* New notion "import public" that allows a proto file to forward the content
it imports to its importers. For example,
// foo.proto
import public "bar.proto";
import "baz.proto";
// qux.proto
import "foo.proto";
// Stuff defined in bar.proto may be used in this file, but stuff from
// baz.proto may NOT be used without importing it explicitly.
This is useful for moving proto files. To move a proto file, just leave
a single "import public" in the old proto file.
* New enum option "allow_alias" that specifies whether different symbols can
be assigned the same numeric value. Default value is "true". Setting it to
false causes the compiler to reject enum definitions where multiple symbols
have the same numeric value.
C++
* New generated method set_allocated_foo(Type* foo) for message and string
fields. This method allows you to set the field to a pre-allocated object
and the containing message takes the ownership of that object.
* Added SetAllocatedExtension() and ReleaseExtension() to extensions API.
* Custom options are now formatted correctly when descriptors are printed in
text format.
* Various speed optimizations.
Java
* Comments in proto files are now collected and put into generated code as
comments for corresponding classes and data members.
* Added Parser to parse directly into messages without a Builder. For
example,
Foo foo = Foo.getParser().ParseFrom(input);
Using Parser is ~25% faster than using Builder to parse messages.
* Added getters/setters to access the underlying ByteString of a string field
directly.
* ByteString now supports more operations: substring(), prepend(), and
append(). The implementation of ByteString uses a binary tree structure
to support these operations efficiently.
* New method findInitializationErrors() that lists all missing required
fields.
* Various code size and speed optimizations.
Python
* Added support for dynamic message creation. DescriptorDatabase,
DescriptorPool, and MessageFactory work like their C++ couterparts to
simplify Descriptor construction from *DescriptorProtos, and MessageFactory
provides a message instance from a Descriptor.
* Added pickle support for protobuf messages.
* Unknown fields are now preserved after parsing.
* Fixed bug where custom options were not correctly populated. Custom
options can be accessed now.
* Added EnumTypeWrapper that provides better accessibility to enum types.
* Added ParseMessage(descriptor, bytes) to generate a new Message instance
from a descriptor and a byte string.
2011-05-01 version 2.4.1:
C++
......
......@@ -102,6 +102,7 @@
<arg value="--proto_path=src/test/java" />
<arg value="../src/google/protobuf/unittest.proto" />
<arg value="../src/google/protobuf/unittest_import.proto" />
<arg value="../src/google/protobuf/unittest_import_public.proto" />
<arg value="../src/google/protobuf/unittest_mset.proto" />
<arg
value="src/test/java/com/google/protobuf/multiple_files_test.proto" />
......@@ -117,6 +118,7 @@
value="../src/google/protobuf/unittest_custom_options.proto" />
<arg value="../src/google/protobuf/unittest_lite.proto" />
<arg value="../src/google/protobuf/unittest_import_lite.proto" />
<arg value="../src/google/protobuf/unittest_import_public_lite.proto" />
<arg value="../src/google/protobuf/unittest_lite_imports_nonlite.proto" />
<arg value="../src/google/protobuf/unittest_enormous_descriptor.proto" />
<arg value="../src/google/protobuf/unittest_no_generic_services.proto" />
......@@ -158,6 +160,13 @@
<include>**/UninitializedMessageException.java</include>
<include>**/UnmodifiableLazyStringList.java</include>
<include>**/WireFormat.java</include>
<include>**/Parser.java</include>
<include>**/AbstractParser.java</include>
<include>**/BoundedByteString.java</include>
<include>**/LiteralByteString.java</include>
<include>**/RopeByteString.java</include>
<include>**/Utf8.java</include>
<include>**/LazyField.java</include>
</includes>
<testIncludes>
<testInclude>**/LiteTest.java</testInclude>
......
......@@ -91,6 +91,14 @@ public abstract class AbstractMessageLite implements MessageLite {
codedOutput.flush();
}
/**
* Package private helper method for AbstractParser to create
* UninitializedMessageException.
*/
UninitializedMessageException newUninitializedMessageException() {
return new UninitializedMessageException(this);
}
/**
* A partial implementation of the {@link Message.Builder} interface which
* implements as many methods of that interface as possible in terms of
......@@ -307,10 +315,12 @@ public abstract class AbstractMessageLite implements MessageLite {
*/
protected static <T> void addAll(final Iterable<T> values,
final Collection<? super T> list) {
for (final T value : values) {
if (value == null) {
throw new NullPointerException();
}
if (values instanceof LazyStringList) {
// For StringOrByteStringLists, check the underlying elements to avoid
// forcing conversions of ByteStrings to Strings.
checkForNullValues(((LazyStringList) values).getUnderlyingElements());
} else {
checkForNullValues(values);
}
if (values instanceof Collection) {
final Collection<T> collection = (Collection<T>) values;
......@@ -321,5 +331,13 @@ public abstract class AbstractMessageLite implements MessageLite {
}
}
}
private static void checkForNullValues(final Iterable<?> values) {
for (final Object value : values) {
if (value == null) {
throw new NullPointerException();
}
}
}
}
}
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.protobuf;
import com.google.protobuf.AbstractMessageLite.Builder.LimitedInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* A partial implementation of the {@link Parser} interface which implements
* as many methods of that interface as possible in terms of other methods.
*
* Note: This class implements all the convenience methods in the
* {@link Parser} interface. See {@link Parser} for related javadocs.
* Subclasses need to implement
* {@link Parser#parsePartialFrom(CodedInputStream, ExtensionRegistryLite)}
*
* @author liujisi@google.com (Pherl Liu)
*/
public abstract class AbstractParser<MessageType extends MessageLite>
implements Parser<MessageType> {
/**
* Creates an UninitializedMessageException for MessageType.
*/
private UninitializedMessageException
newUninitializedMessageException(MessageType message) {
if (message instanceof AbstractMessageLite) {
return ((AbstractMessageLite) message).newUninitializedMessageException();
}
return new UninitializedMessageException(message);
}
/**
* Helper method to check if message is initialized.
*
* @throws InvalidProtocolBufferException if it is not initialized.
* @return The message to check.
*/
private MessageType checkMessageInitialized(MessageType message)
throws InvalidProtocolBufferException {
if (message != null && !message.isInitialized()) {
throw newUninitializedMessageException(message)
.asInvalidProtocolBufferException()
.setUnfinishedMessage(message);
}
return message;
}
private static final ExtensionRegistryLite EMPTY_REGISTRY
= ExtensionRegistryLite.getEmptyRegistry();
public MessageType parsePartialFrom(CodedInputStream input)
throws InvalidProtocolBufferException {
return parsePartialFrom(input, EMPTY_REGISTRY);
}
public MessageType parseFrom(CodedInputStream input,
ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
return checkMessageInitialized(
parsePartialFrom(input, extensionRegistry));
}
public MessageType parseFrom(CodedInputStream input)
throws InvalidProtocolBufferException {
return parseFrom(input, EMPTY_REGISTRY);
}
public MessageType parsePartialFrom(ByteString data,
ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
MessageType message;
try {
CodedInputStream input = data.newCodedInput();
message = parsePartialFrom(input, extensionRegistry);
try {
input.checkLastTagWas(0);
} catch (InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(message);
}
return message;
} catch (InvalidProtocolBufferException e) {
throw e;
} catch (IOException e) {
throw new RuntimeException(
"Reading from a ByteString threw an IOException (should " +
"never happen).", e);
}
}
public MessageType parsePartialFrom(ByteString data)
throws InvalidProtocolBufferException {
return parsePartialFrom(data, EMPTY_REGISTRY);
}
public MessageType parseFrom(ByteString data,
ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
return checkMessageInitialized(parsePartialFrom(data, extensionRegistry));
}
public MessageType parseFrom(ByteString data)
throws InvalidProtocolBufferException {
return parseFrom(data, EMPTY_REGISTRY);
}
public MessageType parsePartialFrom(byte[] data, int off, int len,
ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
try {
CodedInputStream input = CodedInputStream.newInstance(data, off, len);
MessageType message = parsePartialFrom(input, extensionRegistry);
try {
input.checkLastTagWas(0);
} catch (InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(message);
}
return message;
} catch (InvalidProtocolBufferException e) {
throw e;
} catch (IOException e) {
throw new RuntimeException(
"Reading from a byte array threw an IOException (should " +
"never happen).", e);
}
}
public MessageType parsePartialFrom(byte[] data, int off, int len)
throws InvalidProtocolBufferException {
return parsePartialFrom(data, off, len, EMPTY_REGISTRY);
}
public MessageType parsePartialFrom(byte[] data,
ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
return parsePartialFrom(data, 0, data.length, extensionRegistry);
}
public MessageType parsePartialFrom(byte[] data)
throws InvalidProtocolBufferException {
return parsePartialFrom(data, 0, data.length, EMPTY_REGISTRY);
}
public MessageType parseFrom(byte[] data, int off, int len,
ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
return checkMessageInitialized(
parsePartialFrom(data, off, len, extensionRegistry));
}
public MessageType parseFrom(byte[] data, int off, int len)
throws InvalidProtocolBufferException {
return parseFrom(data, off, len, EMPTY_REGISTRY);
}
public MessageType parseFrom(byte[] data,
ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
return parseFrom(data, 0, data.length, extensionRegistry);
}
public MessageType parseFrom(byte[] data)
throws InvalidProtocolBufferException {
return parseFrom(data, EMPTY_REGISTRY);
}
public MessageType parsePartialFrom(InputStream input,
ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
CodedInputStream codedInput = CodedInputStream.newInstance(input);
MessageType message = parsePartialFrom(codedInput, extensionRegistry);
try {
codedInput.checkLastTagWas(0);
} catch (InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(message);
}
return message;
}
public MessageType parsePartialFrom(InputStream input)
throws InvalidProtocolBufferException {
return parsePartialFrom(input, EMPTY_REGISTRY);
}
public MessageType parseFrom(InputStream input,
ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
return checkMessageInitialized(
parsePartialFrom(input, extensionRegistry));
}
public MessageType parseFrom(InputStream input)
throws InvalidProtocolBufferException {
return parseFrom(input, EMPTY_REGISTRY);
}
public MessageType parsePartialDelimitedFrom(
InputStream input,
ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
int size;
try {
int firstByte = input.read();
if (firstByte == -1) {
return null;
}
size = CodedInputStream.readRawVarint32(firstByte, input);
} catch (IOException e) {
throw new InvalidProtocolBufferException(e.getMessage());
}
InputStream limitedInput = new LimitedInputStream(input, size);
return parsePartialFrom(limitedInput, extensionRegistry);
}
public MessageType parsePartialDelimitedFrom(InputStream input)
throws InvalidProtocolBufferException {
return parsePartialDelimitedFrom(input, EMPTY_REGISTRY);
}
public MessageType parseDelimitedFrom(
InputStream input,
ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
return checkMessageInitialized(
parsePartialDelimitedFrom(input, extensionRegistry));
}
public MessageType parseDelimitedFrom(InputStream input)
throws InvalidProtocolBufferException {
return parseDelimitedFrom(input, EMPTY_REGISTRY);
}
}
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.protobuf;
import java.util.NoSuchElementException;
/**
* This class is used to represent the substring of a {@link ByteString} over a
* single byte array. In terms of the public API of {@link ByteString}, you end
* up here by calling {@link ByteString#copyFrom(byte[])} followed by {@link
* ByteString#substring(int, int)}.
*
* <p>This class contains most of the overhead involved in creating a substring
* from a {@link LiteralByteString}. The overhead involves some range-checking
* and two extra fields.
*
* @author carlanton@google.com (Carl Haverl)
*/
class BoundedByteString extends LiteralByteString {
private final int bytesOffset;
private final int bytesLength;
/**
* Creates a {@code BoundedByteString} backed by the sub-range of given array,
* without copying.
*
* @param bytes array to wrap
* @param offset index to first byte to use in bytes
* @param length number of bytes to use from bytes
* @throws IllegalArgumentException if {@code offset < 0}, {@code length < 0},
* or if {@code offset + length >
* bytes.length}.
*/
BoundedByteString(byte[] bytes, int offset, int length) {
super(bytes);
if (offset < 0) {
throw new IllegalArgumentException("Offset too small: " + offset);
}
if (length < 0) {
throw new IllegalArgumentException("Length too small: " + offset);
}
if ((long) offset + length > bytes.length) {
throw new IllegalArgumentException(
"Offset+Length too large: " + offset + "+" + length);
}
this.bytesOffset = offset;
this.bytesLength = length;
}
/**
* Gets the byte at the given index.
* Throws {@link ArrayIndexOutOfBoundsException}
* for backwards-compatibility reasons although it would more properly be
* {@link IndexOutOfBoundsException}.
*
* @param index index of byte
* @return the value
* @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size
*/
@Override
public byte byteAt(int index) {
// We must check the index ourselves as we cannot rely on Java array index
// checking for substrings.
if (index < 0) {
throw new ArrayIndexOutOfBoundsException("Index too small: " + index);
}
if (index >= size()) {
throw new ArrayIndexOutOfBoundsException(
"Index too large: " + index + ", " + size());
}
return bytes[bytesOffset + index];
}
@Override
public int size() {
return bytesLength;
}
@Override
protected int getOffsetIntoBytes() {
return bytesOffset;
}
// =================================================================
// ByteString -> byte[]
@Override
protected void copyToInternal(byte[] target, int sourceOffset,
int targetOffset, int numberToCopy) {
System.arraycopy(bytes, getOffsetIntoBytes() + sourceOffset, target,
targetOffset, numberToCopy);
}
// =================================================================
// ByteIterator
@Override
public ByteIterator iterator() {
return new BoundedByteIterator();
}
private class BoundedByteIterator implements ByteIterator {
private int position;
private final int limit;
private BoundedByteIterator() {
position = getOffsetIntoBytes();
limit = position + size();
}
public boolean hasNext() {
return (position < limit);
}
public Byte next() {
// Boxing calls Byte.valueOf(byte), which does not instantiate.
return nextByte();
}
public byte nextByte() {
if (position >= limit) {
throw new NoSuchElementException();
}
return bytes[position++];
}
public void remove() {
throw new UnsupportedOperationException();
}
}
}
......@@ -243,6 +243,23 @@ public final class CodedInputStream {
--recursionDepth;
}
/** Read a {@code group} field value from the stream. */
public <T extends MessageLite> T readGroup(
final int fieldNumber,
final Parser<T> parser,
final ExtensionRegistryLite extensionRegistry)
throws IOException {
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.recursionLimitExceeded();
}
++recursionDepth;
T result = parser.parsePartialFrom(this, extensionRegistry);
checkLastTagWas(
WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
--recursionDepth;
return result;
}
/**
* Reads a {@code group} field value from the stream and merges it into the
* given {@link UnknownFieldSet}.
......@@ -278,6 +295,24 @@ public final class CodedInputStream {
popLimit(oldLimit);
}
/** Read an embedded message field value from the stream. */
public <T extends MessageLite> T readMessage(
final Parser<T> parser,
final ExtensionRegistryLite extensionRegistry)
throws IOException {
int length = readRawVarint32();
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.recursionLimitExceeded();
}
final int oldLimit = pushLimit(length);
++recursionDepth;
T result = parser.parsePartialFrom(this, extensionRegistry);
checkLastTagWas(0);
--recursionDepth;
popLimit(oldLimit);
return result;
}
/** Read a {@code bytes} field value from the stream. */
public ByteString readBytes() throws IOException {
final int size = readRawVarint32();
......@@ -601,7 +636,7 @@ public final class CodedInputStream {
* refreshing its buffer. If you need to prevent reading past a certain
* point in the underlying {@code InputStream} (e.g. because you expect it to
* contain more data after the end of the message which you need to handle
* differently) then you must place a wrapper around you {@code InputStream}
* differently) then you must place a wrapper around your {@code InputStream}
* which limits the amount of data that can be read from it.
*
* @return the old limit.
......@@ -676,7 +711,7 @@ public final class CodedInputStream {
/**
* Called with {@code this.buffer} is empty to read more bytes from the
* input. If {@code mustSucceed} is true, refillBuffer() gurantees that
* input. If {@code mustSucceed} is true, refillBuffer() guarantees that
* either there will be at least one byte in the buffer when it returns
* or it will throw an exception. If {@code mustSucceed} is false,
* refillBuffer() returns false if no more bytes were available.
......@@ -879,7 +914,7 @@ public final class CodedInputStream {
refillBuffer(true);
}
bufferPos = size - pos;
bufferPos = size - pos;
}
}
}
......@@ -30,10 +30,10 @@
package com.google.protobuf;
import java.io.OutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
/**
* Encodes and writes protocol message fields.
......@@ -539,6 +539,15 @@ public final class CodedOutputStream {
return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value);
}
/**
* Compute the number of bytes that would be needed to encode an
* embedded message in lazy field, including tag.
*/
public static int computeLazyFieldSize(final int fieldNumber,
final LazyField value) {
return computeTagSize(fieldNumber) + computeLazyFieldSizeNoTag(value);
}
/**
* Compute the number of bytes that would be needed to encode a
* {@code uint32} field, including tag.
......@@ -614,6 +623,18 @@ public final class CodedOutputStream {
computeBytesSize(WireFormat.MESSAGE_SET_MESSAGE, value);
}
/**
* Compute the number of bytes that would be needed to encode an
* lazily parsed MessageSet extension field to the stream. For
* historical reasons, the wire format differs from normal fields.
*/
public static int computeLazyFieldMessageSetExtensionSize(
final int fieldNumber, final LazyField value) {
return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2 +
computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber) +
computeLazyFieldSize(WireFormat.MESSAGE_SET_MESSAGE, value);
}
// -----------------------------------------------------------------
/**
......@@ -729,6 +750,15 @@ public final class CodedOutputStream {
return computeRawVarint32Size(size) + size;
}
/**
* Compute the number of bytes that would be needed to encode an embedded
* message stored in lazy field.
*/
public static int computeLazyFieldSizeNoTag(final LazyField value) {
final int size = value.getSerializedSize();
return computeRawVarint32Size(size) + size;
}
/**
* Compute the number of bytes that would be needed to encode a
* {@code bytes} field.
......
......@@ -35,6 +35,7 @@ import com.google.protobuf.Descriptors.FieldDescriptor;
import java.io.InputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
/**
......@@ -160,7 +161,9 @@ public final class DynamicMessage extends AbstractMessage {
verifyContainingType(field);
Object result = fields.getField(field);
if (result == null) {
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
if (field.isRepeated()) {
result = Collections.emptyList();
} else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
result = getDefaultInstance(field.getMessageType());
} else {
result = field.getDefaultValue();
......@@ -198,10 +201,12 @@ public final class DynamicMessage extends AbstractMessage {
return fields.isInitialized();
}
@Override
public boolean isInitialized() {
return isInitialized(type, fields);
}
@Override
public void writeTo(CodedOutputStream output) throws IOException {
if (type.getOptions().getMessageSetWireFormat()) {
fields.writeMessageSetTo(output);
......@@ -212,6 +217,7 @@ public final class DynamicMessage extends AbstractMessage {
}
}
@Override
public int getSerializedSize() {
int size = memoizedSize;
if (size != -1) return size;
......@@ -236,6 +242,26 @@ public final class DynamicMessage extends AbstractMessage {
return newBuilderForType().mergeFrom(this);
}
public Parser<DynamicMessage> getParserForType() {
return new AbstractParser<DynamicMessage>() {
public DynamicMessage parsePartialFrom(
CodedInputStream input,
ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
Builder builder = newBuilder(type);
try {
builder.mergeFrom(input, extensionRegistry);
} catch (InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(builder.buildPartial());
} catch (IOException e) {
throw new InvalidProtocolBufferException(e.getMessage())
.setUnfinishedMessage(builder.buildPartial());
}
return builder.buildPartial();
}
};
}
/** Verifies that the field is a field of this message. */
private void verifyContainingType(FieldDescriptor field) {
if (field.getContainingType() != type) {
......@@ -264,14 +290,18 @@ public final class DynamicMessage extends AbstractMessage {
// ---------------------------------------------------------------
// Implementation of Message.Builder interface.
@Override
public Builder clear() {
if (fields == null) {
throw new IllegalStateException("Cannot call clear() after build().");
if (fields.isImmutable()) {
fields = FieldSet.newFieldSet();
} else {
fields.clear();
}
fields.clear();
unknownFields = UnknownFieldSet.getDefaultInstance();
return this;
}
@Override
public Builder mergeFrom(Message other) {
if (other instanceof DynamicMessage) {
// This should be somewhat faster than calling super.mergeFrom().
......@@ -280,6 +310,7 @@ public final class DynamicMessage extends AbstractMessage {
throw new IllegalArgumentException(
"mergeFrom(Message) can only merge messages of the same type.");
}
ensureIsMutable();
fields.mergeFrom(otherDynamicMessage.fields);
mergeUnknownFields(otherDynamicMessage.unknownFields);
return this;
......@@ -289,8 +320,7 @@ public final class DynamicMessage extends AbstractMessage {
}
public DynamicMessage build() {
// If fields == null, we'll throw an appropriate exception later.
if (fields != null && !isInitialized()) {
if (!isInitialized()) {
throw newUninitializedMessageException(
new DynamicMessage(type, fields, unknownFields));
}
......@@ -312,21 +342,17 @@ public final class DynamicMessage extends AbstractMessage {
}
public DynamicMessage buildPartial() {
if (fields == null) {
throw new IllegalStateException(
"build() has already been called on this Builder.");
}
fields.makeImmutable();
DynamicMessage result =
new DynamicMessage(type, fields, unknownFields);
fields = null;
unknownFields = null;
return result;
}
@Override
public Builder clone() {
Builder result = new Builder(type);
result.fields.mergeFrom(fields);
result.mergeUnknownFields(unknownFields);
return result;
}
......@@ -377,12 +403,14 @@ public final class DynamicMessage extends AbstractMessage {
public Builder setField(FieldDescriptor field, Object value) {
verifyContainingType(field);
ensureIsMutable();
fields.setField(field, value);
return this;
}
public Builder clearField(FieldDescriptor field) {
verifyContainingType(field);
ensureIsMutable();
fields.clearField(field);
return this;
}
......@@ -400,12 +428,14 @@ public final class DynamicMessage extends AbstractMessage {
public Builder setRepeatedField(FieldDescriptor field,
int index, Object value) {
verifyContainingType(field);
ensureIsMutable();
fields.setRepeatedField(field, index, value);
return this;
}
public Builder addRepeatedField(FieldDescriptor field, Object value) {
verifyContainingType(field);
ensureIsMutable();
fields.addRepeatedField(field, value);
return this;
}
......@@ -419,6 +449,7 @@ public final class DynamicMessage extends AbstractMessage {
return this;
}
@Override
public Builder mergeUnknownFields(UnknownFieldSet unknownFields) {
this.unknownFields =
UnknownFieldSet.newBuilder(this.unknownFields)
......@@ -434,5 +465,18 @@ public final class DynamicMessage extends AbstractMessage {
"FieldDescriptor does not match message type.");
}
}
private void ensureIsMutable() {
if (fields.isImmutable()) {
fields = fields.clone();
}
}
@Override
public com.google.protobuf.Message.Builder getFieldBuilder(FieldDescriptor field) {
// TODO(xiangl): need implementation for dynamic message
throw new UnsupportedOperationException(
"getFieldBuilder() called on a dynamic message type.");
}
}
}
......@@ -43,7 +43,7 @@ import java.util.Map;
* make sense to mix the two, since if you have any regular types in your
* program, you then require the full runtime and lose all the benefits of
* the lite runtime, so you might as well make all your types be regular types.
* However, in some cases (e.g. when depending on multiple third-patry libraries
* However, in some cases (e.g. when depending on multiple third-party libraries
* where one uses lite types and one uses regular), you may find yourself
* wanting to mix the two. In this case things get more complicated.
* <p>
......@@ -71,6 +71,22 @@ import java.util.Map;
* @author kenton@google.com Kenton Varda
*/
public class ExtensionRegistryLite {
// Set true to enable lazy parsing feature for MessageSet.
//
// TODO(xiangl): Now we use a global flag to control whether enable lazy
// parsing feature for MessageSet, which may be too crude for some
// applications. Need to support this feature on smaller granularity.
private static volatile boolean eagerlyParseMessageSets = false;
public static boolean isEagerlyParseMessageSets() {
return eagerlyParseMessageSets;
}
public static void setEagerlyParseMessageSets(boolean isEagerlyParse) {
eagerlyParseMessageSets = isEagerlyParse;
}
/** Construct a new, empty instance. */
public static ExtensionRegistryLite newInstance() {
return new ExtensionRegistryLite();
......
......@@ -103,85 +103,32 @@ public class Internal {
* Helper called by generated code to determine if a byte array is a valid
* UTF-8 encoded string such that the original bytes can be converted to
* a String object and then back to a byte array round tripping the bytes
* without loss.
* <p>
* This is inspired by UTF_8.java in sun.nio.cs.
* without loss. More precisely, returns {@code true} whenever:
* <pre> {@code
* Arrays.equals(byteString.toByteArray(),
* new String(byteString.toByteArray(), "UTF-8").getBytes("UTF-8"))
* }</pre>
*
* <p>This method rejects "overlong" byte sequences, as well as
* 3-byte sequences that would map to a surrogate character, in
* accordance with the restricted definition of UTF-8 introduced in
* Unicode 3.1. Note that the UTF-8 decoder included in Oracle's
* JDK has been modified to also reject "overlong" byte sequences,
* but currently (2011) still accepts 3-byte surrogate character
* byte sequences.
*
* <p>See the Unicode Standard,</br>
* Table 3-6. <em>UTF-8 Bit Distribution</em>,</br>
* Table 3-7. <em>Well Formed UTF-8 Byte Sequences</em>.
*
* <p>As of 2011-02, this method simply returns the result of {@link
* ByteString#isValidUtf8()}. Calling that method directly is preferred.
*
* @param byteString the string to check
* @return whether the byte array is round trippable
*/
public static boolean isValidUtf8(ByteString byteString) {
int index = 0;
int size = byteString.size();
// To avoid the masking, we could change this to use bytes;
// Then X > 0xC2 gets turned into X < -0xC2; X < 0x80
// gets turned into X >= 0, etc.
while (index < size) {
int byte1 = byteString.byteAt(index++) & 0xFF;
if (byte1 < 0x80) {
// fast loop for single bytes
continue;
// we know from this point on that we have 2-4 byte forms
} else if (byte1 < 0xC2 || byte1 > 0xF4) {
// catch illegal first bytes: < C2 or > F4
return false;
}
if (index >= size) {
// fail if we run out of bytes
return false;
}
int byte2 = byteString.byteAt(index++) & 0xFF;
if (byte2 < 0x80 || byte2 > 0xBF) {
// general trail-byte test
return false;
}
if (byte1 <= 0xDF) {
// two-byte form; general trail-byte test is sufficient
continue;
}
// we know from this point on that we have 3 or 4 byte forms
if (index >= size) {
// fail if we run out of bytes
return false;
}
int byte3 = byteString.byteAt(index++) & 0xFF;
if (byte3 < 0x80 || byte3 > 0xBF) {
// general trail-byte test
return false;
}
if (byte1 <= 0xEF) {
// three-byte form. Vastly more frequent than four-byte forms
// The following has an extra test, but not worth restructuring
if (byte1 == 0xE0 && byte2 < 0xA0 ||
byte1 == 0xED && byte2 > 0x9F) {
// check special cases of byte2
return false;
}
} else {
// four-byte form
if (index >= size) {
// fail if we run out of bytes
return false;
}
int byte4 = byteString.byteAt(index++) & 0xFF;
if (byte4 < 0x80 || byte4 > 0xBF) {
// general trail-byte test
return false;
}
// The following has an extra test, but not worth restructuring
if (byte1 == 0xF0 && byte2 < 0x90 ||
byte1 == 0xF4 && byte2 > 0x8F) {
// check special cases of byte2
return false;
}
}
}
return true;
return byteString.isValidUtf8();
}
/**
......
......@@ -40,11 +40,32 @@ import java.io.IOException;
*/
public class InvalidProtocolBufferException extends IOException {
private static final long serialVersionUID = -1616151763072450476L;
private MessageLite unfinishedMessage = null;
public InvalidProtocolBufferException(final String description) {
super(description);
}
/**
* Attaches an unfinished message to the exception to support best-effort
* parsing in {@code Parser} interface.
*
* @return this
*/
public InvalidProtocolBufferException setUnfinishedMessage(
MessageLite unfinishedMessage) {
this.unfinishedMessage = unfinishedMessage;
return this;
}
/**
* Returns the unfinished message attached to the exception, or null if
* no message is attached.
*/
public MessageLite getUnfinishedMessage() {
return unfinishedMessage;
}
static InvalidProtocolBufferException truncatedMessage() {
return new InvalidProtocolBufferException(
"While parsing a protocol message, the input ended unexpectedly " +
......
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.protobuf;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map.Entry;
/**
* LazyField encapsulates the logic of lazily parsing message fields. It stores
* the message in a ByteString initially and then parse it on-demand.
*
* LazyField is thread-compatible e.g. concurrent read are safe, however,
* synchronizations are needed under read/write situations.
*
* Now LazyField is only used to lazily load MessageSet.
* TODO(xiangl): Use LazyField to lazily load all messages.
*
* @author xiangl@google.com (Xiang Li)
*/
class LazyField {
final private MessageLite defaultInstance;
final private ExtensionRegistryLite extensionRegistry;
// Mutable because it is initialized lazily.
private ByteString bytes;
private volatile MessageLite value;
private volatile boolean isDirty = false;
public LazyField(MessageLite defaultInstance,
ExtensionRegistryLite extensionRegistry, ByteString bytes) {
this.defaultInstance = defaultInstance;
this.extensionRegistry = extensionRegistry;
this.bytes = bytes;
}
public MessageLite getValue() {
ensureInitialized();
return value;
}
/**
* LazyField is not thread-safe for write access. Synchronizations are needed
* under read/write situations.
*/
public MessageLite setValue(MessageLite value) {
MessageLite originalValue = this.value;
this.value = value;
bytes = null;
isDirty = true;
return originalValue;
}
/**
* Due to the optional field can be duplicated at the end of serialized
* bytes, which will make the serialized size changed after LazyField
* parsed. Be careful when using this method.
*/
public int getSerializedSize() {
if (isDirty) {
return value.getSerializedSize();
}
return bytes.size();
}
public ByteString toByteString() {
if (!isDirty) {
return bytes;
}
synchronized (this) {
if (!isDirty) {
return bytes;
}
bytes = value.toByteString();
isDirty = false;
return bytes;
}
}
@Override
public int hashCode() {
ensureInitialized();
return value.hashCode();
}
@Override
public boolean equals(Object obj) {
ensureInitialized();
return value.equals(obj);
}
@Override
public String toString() {
ensureInitialized();
return value.toString();
}
private void ensureInitialized() {
if (value != null) {
return;
}
synchronized (this) {
if (value != null) {
return;
}
try {
if (bytes != null) {
value = defaultInstance.getParserForType()
.parseFrom(bytes, extensionRegistry);
}
} catch (IOException e) {
// TODO(xiangl): Refactory the API to support the exception thrown from
// lazily load messages.
}
}
}
// ====================================================
/**
* LazyEntry and LazyIterator are used to encapsulate the LazyField, when
* users iterate all fields from FieldSet.
*/
static class LazyEntry<K> implements Entry<K, Object> {
private Entry<K, LazyField> entry;
private LazyEntry(Entry<K, LazyField> entry) {
this.entry = entry;
}
@Override
public K getKey() {
return entry.getKey();
}
@Override
public Object getValue() {
LazyField field = entry.getValue();
if (field == null) {
return null;
}
return field.getValue();
}
public LazyField getField() {
return entry.getValue();
}
@Override
public Object setValue(Object value) {
if (!(value instanceof MessageLite)) {
throw new IllegalArgumentException(
"LazyField now only used for MessageSet, "
+ "and the value of MessageSet must be an instance of MessageLite");
}
return entry.getValue().setValue((MessageLite) value);
}
}
static class LazyIterator<K> implements Iterator<Entry<K, Object>> {
private Iterator<Entry<K, Object>> iterator;
public LazyIterator(Iterator<Entry<K, Object>> iterator) {
this.iterator = iterator;
}
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@SuppressWarnings("unchecked")
@Override
public Entry<K, Object> next() {
Entry<K, ?> entry = iterator.next();
if (entry.getValue() instanceof LazyField) {
return new LazyEntry<K>((Entry<K, LazyField>) entry);
}
return (Entry<K, Object>) entry;
}
@Override
public void remove() {
iterator.remove();
}
}
}
......@@ -33,8 +33,9 @@ package com.google.protobuf;
import java.util.List;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.RandomAccess;
import java.util.Collection;
import java.util.Collections;
import java.util.RandomAccess;
/**
* An implementation of {@link LazyStringList} that wraps an ArrayList. Each
......@@ -72,6 +73,11 @@ public class LazyStringArrayList extends AbstractList<String>
list = new ArrayList<Object>();
}
public LazyStringArrayList(LazyStringList from) {
list = new ArrayList<Object>(from.size());
addAll(from);
}
public LazyStringArrayList(List<String> from) {
list = new ArrayList<Object>(from);
}
......@@ -84,7 +90,7 @@ public class LazyStringArrayList extends AbstractList<String>
} else {
ByteString bs = (ByteString) o;
String s = bs.toStringUtf8();
if (Internal.isValidUtf8(bs)) {
if (bs.isValidUtf8()) {
list.set(index, s);
}
return s;
......@@ -108,9 +114,22 @@ public class LazyStringArrayList extends AbstractList<String>
modCount++;
}
@Override
public boolean addAll(Collection<? extends String> c) {
// The default implementation of AbstractCollection.addAll(Collection)
// delegates to add(Object). This implementation instead delegates to
// addAll(int, Collection), which makes a special case for Collections
// which are instances of LazyStringList.
return addAll(size(), c);
}
@Override
public boolean addAll(int index, Collection<? extends String> c) {
boolean ret = list.addAll(index, c);
// When copying from another LazyStringList, directly copy the underlying
// elements rather than forcing each element to be decoded to a String.
Collection<?> collection = c instanceof LazyStringList
? ((LazyStringList) c).getUnderlyingElements() : c;
boolean ret = list.addAll(index, collection);
modCount++;
return ret;
}
......@@ -152,4 +171,9 @@ public class LazyStringArrayList extends AbstractList<String>
return ((ByteString) o).toStringUtf8();
}
}
@Override
public List<?> getUnderlyingElements() {
return Collections.unmodifiableList(list);
}
}
......@@ -33,7 +33,7 @@ package com.google.protobuf;
import java.util.List;
/**
* An interface extending List&lt;String&gt; that also provides access to the
* An interface extending {@code List<String>} that also provides access to the
* items of the list as UTF8-encoded ByteString objects. This is used by the
* protocol buffer implementation to support lazily converting bytes parsed
* over the wire to String objects until needed and also increases the
......@@ -41,9 +41,9 @@ import java.util.List;
* ByteString is already cached.
* <p>
* This only adds additional methods that are required for the use in the
* protocol buffer code in order to be able successfuly round trip byte arrays
* protocol buffer code in order to be able successfully round trip byte arrays
* through parsing and serialization without conversion to strings. It's not
* attempting to support the functionality of say List&ltByteString&gt, hence
* attempting to support the functionality of say {@code List<ByteString>}, hence
* why only these two very specific methods are added.
*
* @author jonp@google.com (Jon Perlow)
......@@ -56,7 +56,7 @@ public interface LazyStringList extends List<String> {
* @param index index of the element to return
* @return the element at the specified position in this list
* @throws IndexOutOfBoundsException if the index is out of range
* (<tt>index &lt; 0 || index &gt;= size()</tt>)
* ({@code index < 0 || index >= size()})
*/
ByteString getByteString(int index);
......@@ -69,4 +69,13 @@ public interface LazyStringList extends List<String> {
* is not supported by this list
*/
void add(ByteString element);
/**
* Returns an unmodifiable List of the underlying elements, each of
* which is either a {@code String} or its equivalent UTF-8 encoded
* {@code ByteString}. It is an error for the caller to modify the returned
* List, and attempting to do so will result in an
* {@link UnsupportedOperationException}.
*/
List<?> getUnderlyingElements();
}
This diff is collapsed.
......@@ -50,25 +50,28 @@ import java.util.Map;
*/
public interface Message extends MessageLite, MessageOrBuilder {
// (From MessageLite, re-declared here only for return type covariance.)
Parser<? extends Message> getParserForType();
// -----------------------------------------------------------------
// Comparison and hashing
/**
* Compares the specified object with this message for equality. Returns
* <tt>true</tt> if the given object is a message of the same type (as
* {@code true} if the given object is a message of the same type (as
* defined by {@code getDescriptorForType()}) and has identical values for
* all of its fields. Subclasses must implement this; inheriting
* {@code Object.equals()} is incorrect.
*
* @param other object to be compared for equality with this message
* @return <tt>true</tt> if the specified object is equal to this message
* @return {@code true} if the specified object is equal to this message
*/
@Override
boolean equals(Object other);
/**
* Returns the hash code value for this message. The hash code of a message
* should mix the message's type (object identity of the decsriptor) with its
* should mix the message's type (object identity of the descriptor) with its
* contents (known and unknown field values). Subclasses must implement this;
* inheriting {@code Object.hashCode()} is incorrect.
*
......@@ -83,7 +86,8 @@ public interface Message extends MessageLite, MessageOrBuilder {
/**
* Converts the message to a string in protocol buffer text format. This is
* just a trivial wrapper around {@link TextFormat#printToString(Message)}.
* just a trivial wrapper around {@link
* TextFormat#printToString(MessageOrBuilder)}.
*/
@Override
String toString();
......@@ -144,6 +148,24 @@ public interface Message extends MessageLite, MessageOrBuilder {
*/
Builder newBuilderForField(Descriptors.FieldDescriptor field);
/**
* Get a nested builder instance for the given field.
* <p>
* Normally, we hold a reference to the immutable message object for the
* message type field. Some implementations(the generated message builders),
* however, can also hold a reference to the builder object (a nested
* builder) for the field.
* <p>
* If the field is already backed up by a nested builder, the nested builder
* will be returned. Otherwise, a new field builder will be created and
* returned. The original message field (if exist) will be merged into the
* field builder, which will then be nested into its parent builder.
* <p>
* NOTE: implementations that do not support nested builders will throw
* <code>UnsupportedException</code>.
*/
Builder getFieldBuilder(Descriptors.FieldDescriptor field);
/**
* Sets a field to the given value. The value must be of the correct type
* for this field, i.e. the same type that
......
......@@ -79,6 +79,12 @@ public interface MessageLite extends MessageLiteOrBuilder {
*/
int getSerializedSize();
/**
* Gets the parser for a message of the same type as this message.
*/
Parser<? extends MessageLite> getParserForType();
// -----------------------------------------------------------------
// Convenience methods.
......@@ -144,11 +150,8 @@ public interface MessageLite extends MessageLiteOrBuilder {
Builder clear();
/**
* Construct the final message. Once this is called, the Builder is no
* longer valid, and calling any other method will result in undefined
* behavior and may throw a NullPointerException. If you need to continue
* working with the builder after calling {@code build()}, {@code clone()}
* it first.
* Constructs the message based on the state of the Builder. Subsequent
* changes to the Builder will not affect the returned message.
* @throws UninitializedMessageException The message is missing one or more
* required fields (i.e. {@link #isInitialized()} returns false).
* Use {@link #buildPartial()} to bypass this check.
......@@ -158,11 +161,7 @@ public interface MessageLite extends MessageLiteOrBuilder {
/**
* Like {@link #build()}, but does not throw an exception if the message
* is missing required fields. Instead, a partial message is returned.
* Once this is called, the Builder is no longer valid, and calling any
* will result in undefined behavior and may throw a NullPointerException.
*
* If you need to continue working with the builder after calling
* {@code buildPartial()}, {@code clone()} it first.
* Subsequent changes to the Builder will not affect the returned message.
*/
MessageLite buildPartial();
......@@ -174,7 +173,7 @@ public interface MessageLite extends MessageLiteOrBuilder {
/**
* Parses a message of this type from the input and merges it with this
* message, as if using {@link Builder#mergeFrom(MessageLite)}.
* message.
*
* <p>Warning: This does not verify that all required fields are present in
* the input message. If you call {@link #build()} without setting all
......@@ -184,11 +183,6 @@ public interface MessageLite extends MessageLiteOrBuilder {
* <ul>
* <li>Call {@link #isInitialized()} to verify that all required fields
* are set before building.
* <li>Parse the message separately using one of the static
* {@code parseFrom} methods, then use {@link #mergeFrom(MessageLite)}
* to merge it with this one. {@code parseFrom} will throw an
* {@link InvalidProtocolBufferException} (an {@code IOException})
* if some required fields are missing.
* <li>Use {@code buildPartial()} to build, which ignores missing
* required fields.
* </ul>
......@@ -225,7 +219,7 @@ public interface MessageLite extends MessageLiteOrBuilder {
/**
* Parse {@code data} as a message of this type and merge it with the
* message being built. This is just a small wrapper around
* {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
* {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}.
*
* @return this
*/
......@@ -255,7 +249,7 @@ public interface MessageLite extends MessageLiteOrBuilder {
/**
* Parse {@code data} as a message of this type and merge it with the
* message being built. This is just a small wrapper around
* {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
* {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}.
*
* @return this
*/
......@@ -266,7 +260,7 @@ public interface MessageLite extends MessageLiteOrBuilder {
/**
* Parse {@code data} as a message of this type and merge it with the
* message being built. This is just a small wrapper around
* {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
* {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}.
*
* @return this
*/
......@@ -293,7 +287,7 @@ public interface MessageLite extends MessageLiteOrBuilder {
/**
* Parse a message of this type from {@code input} and merge it with the
* message being built. This is just a small wrapper around
* {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
* {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}.
*
* @return this
*/
......@@ -308,9 +302,9 @@ public interface MessageLite extends MessageLiteOrBuilder {
* {@link MessageLite#writeDelimitedTo(OutputStream)} to write messages in
* this format.
*
* @returns True if successful, or false if the stream is at EOF when the
* method starts. Any other error (including reaching EOF during
* parsing) will cause an exception to be thrown.
* @return True if successful, or false if the stream is at EOF when the
* method starts. Any other error (including reaching EOF during
* parsing) will cause an exception to be thrown.
*/
boolean mergeDelimitedFrom(InputStream input)
throws IOException;
......
......@@ -52,6 +52,8 @@ public interface MessageLiteOrBuilder {
/**
* Returns true if all required fields in the message and all embedded
* messages are set, false otherwise.
*
* <p>See also: {@link MessageOrBuilder#getInitializationErrorString()}
*/
boolean isInitialized();
......
......@@ -30,6 +30,7 @@
package com.google.protobuf;
import java.util.List;
import java.util.Map;
/**
......@@ -44,6 +45,24 @@ public interface MessageOrBuilder extends MessageLiteOrBuilder {
//@Override (Java 1.6 override semantics, but we must support 1.5)
Message getDefaultInstanceForType();
/**
* Returns a list of field paths (e.g. "foo.bar.baz") of required fields
* which are not set in this message. You should call
* {@link MessageLiteOrBuilder#isInitialized()} first to check if there
* are any missing fields, as that method is likely to be much faster
* than this one even when the message is fully-initialized.
*/
List<String> findInitializationErrors();
/**
* Returns a comma-delimited list of required fields which are not set
* in this message object. You should call
* {@link MessageLiteOrBuilder#isInitialized()} first to check if there
* are any missing fields, as that method is likely to be much faster
* than this one even when the message is fully-initialized.
*/
String getInitializationErrorString();
/**
* Get the message's type's descriptor. This differs from the
* {@code getDescriptor()} method of generated message classes in that
......@@ -80,7 +99,7 @@ public interface MessageOrBuilder extends MessageLiteOrBuilder {
/**
* Obtains the value of the given field, or the default value if it is
* not set. For primitive fields, the boxed primitive value is returned.
* For enum fields, the EnumValueDescriptor for the value is returend. For
* For enum fields, the EnumValueDescriptor for the value is returned. For
* embedded message fields, the sub-message is returned. For repeated
* fields, a java.util.List is returned.
*/
......@@ -98,7 +117,7 @@ public interface MessageOrBuilder extends MessageLiteOrBuilder {
/**
* Gets an element of a repeated field. For primitive fields, the boxed
* primitive value is returned. For enum fields, the EnumValueDescriptor
* for the value is returend. For embedded message fields, the sub-message
* for the value is returned. For embedded message fields, the sub-message
* is returned.
* @throws IllegalArgumentException The field is not a repeated field, or
* {@code field.getContainingType() != getDescriptorForType()}.
......
This diff is collapsed.
......@@ -37,22 +37,22 @@ import java.util.Collections;
import java.util.List;
/**
* <code>RepeatedFieldBuilder</code> implements a structure that a protocol
* {@code RepeatedFieldBuilder} implements a structure that a protocol
* message uses to hold a repeated field of other protocol messages. It supports
* the classical use case of adding immutable {@link Message}'s to the
* repeated field and is highly optimized around this (no extra memory
* allocations and sharing of immutable arrays).
* <br>
* It also supports the additional use case of adding a {@link Message.Builder}
* to the repeated field and deferring conversion of that <code>Builder</code>
* to an immutable <code>Message</code>. In this way, it's possible to maintain
* a tree of <code>Builder</code>'s that acts as a fully read/write data
* to the repeated field and deferring conversion of that {@code Builder}
* to an immutable {@code Message}. In this way, it's possible to maintain
* a tree of {@code Builder}'s that acts as a fully read/write data
* structure.
* <br>
* Logically, one can think of a tree of builders as converting the entire tree
* to messages when build is called on the root or when any method is called
* that desires a Message instead of a Builder. In terms of the implementation,
* the <code>SingleFieldBuilder</code> and <code>RepeatedFieldBuilder</code>
* the {@code SingleFieldBuilder} and {@code RepeatedFieldBuilder}
* classes cache messages that were created so that messages only need to be
* created when some change occured in its builder or a builder for one of its
* descendants.
......@@ -192,7 +192,7 @@ public class RepeatedFieldBuilder
/**
* Get the message at the specified index. If the message is currently stored
* as a <code>Builder</code>, it is converted to a <code>Message</code> by
* as a {@code Builder}, it is converted to a {@code Message} by
* calling {@link Message.Builder#buildPartial} on it.
*
* @param index the index of the message to get
......@@ -204,7 +204,7 @@ public class RepeatedFieldBuilder
/**
* Get the message at the specified index. If the message is currently stored
* as a <code>Builder</code>, it is converted to a <code>Message</code> by
* as a {@code Builder}, it is converted to a {@code Message} by
* calling {@link Message.Builder#buildPartial} on it.
*
* @param index the index of the message to get
......
This diff is collapsed.
......@@ -31,21 +31,21 @@
package com.google.protobuf;
/**
* <code>SingleFieldBuilder</code> implements a structure that a protocol
* {@code SingleFieldBuilder} implements a structure that a protocol
* message uses to hold a single field of another protocol message. It supports
* the classical use case of setting an immutable {@link Message} as the value
* of the field and is highly optimized around this.
* <br>
* It also supports the additional use case of setting a {@link Message.Builder}
* as the field and deferring conversion of that <code>Builder</code>
* to an immutable <code>Message</code>. In this way, it's possible to maintain
* a tree of <code>Builder</code>'s that acts as a fully read/write data
* as the field and deferring conversion of that {@code Builder}
* to an immutable {@code Message}. In this way, it's possible to maintain
* a tree of {@code Builder}'s that acts as a fully read/write data
* structure.
* <br>
* Logically, one can think of a tree of builders as converting the entire tree
* to messages when build is called on the root or when any method is called
* that desires a Message instead of a Builder. In terms of the implementation,
* the <code>SingleFieldBuilder</code> and <code>RepeatedFieldBuilder</code>
* the {@code SingleFieldBuilder} and {@code RepeatedFieldBuilder}
* classes cache messages that were created so that messages only need to be
* created when some change occured in its builder or a builder for one of its
* descendants.
......@@ -99,7 +99,7 @@ public class SingleFieldBuilder
/**
* Get the message for the field. If the message is currently stored
* as a <code>Builder</code>, it is converted to a <code>Message</code> by
* as a {@code Builder}, it is converted to a {@code Message} by
* calling {@link Message.Builder#buildPartial} on it. If no message has
* been set, returns the default instance of the message.
*
......
......@@ -51,14 +51,14 @@ import java.util.SortedMap;
* remaining entries are stored in an overflow map. Iteration over the entries
* in the map should be done as follows:
*
* <pre>
* for (int i = 0; i &lt; fieldMap.getNumArrayEntries(); i++) {
* <pre> {@code
* for (int i = 0; i < fieldMap.getNumArrayEntries(); i++) {
* process(fieldMap.getArrayEntryAt(i));
* }
* for (Map.Entry&lt;K, V&gt; entry : fieldMap.getOverflowEntries()) {
* for (Map.Entry<K, V> entry : fieldMap.getOverflowEntries()) {
* process(entry);
* }
* </pre>
* }</pre>
*
* The resulting iteration is in order of ascending field tag number. The
* object returned by {@link #entrySet()} adheres to the same contract but is
......@@ -394,7 +394,7 @@ class SmallSortedMap<K extends Comparable<K>, V> extends AbstractMap<K, V> {
/**
* Entry implementation that implements Comparable in order to support
* binary search witin the entry array. Also checks mutability in
* binary search within the entry array. Also checks mutability in
* {@link #setValue()}.
*/
private class Entry implements Map.Entry<K, V>, Comparable<Entry> {
......
......@@ -46,7 +46,7 @@ import java.util.TreeMap;
* {@code UnknownFieldSet} is used to keep track of fields which were seen when
* parsing a protocol message but whose field numbers or types are unrecognized.
* This most frequently occurs when new fields are added to a message type
* and then messages containing those feilds are read by old software that was
* and then messages containing those fields are read by old software that was
* compiled before the new types were added.
*
* <p>Every {@link Message} contains an {@code UnknownFieldSet} (and every
......@@ -468,7 +468,7 @@ public final class UnknownFieldSet implements MessageLite {
/**
* Parse a single field from {@code input} and merge it into this set.
* @param tag The field's tag number, which was already parsed.
* @return {@code false} if the tag is an engroup tag.
* @return {@code false} if the tag is an end group tag.
*/
public boolean mergeFieldFrom(final int tag, final CodedInputStream input)
throws IOException {
......@@ -950,4 +950,29 @@ public final class UnknownFieldSet implements MessageLite {
}
}
}
/**
* Parser to implement MessageLite interface.
*/
public static final class Parser extends AbstractParser<UnknownFieldSet> {
public UnknownFieldSet parsePartialFrom(
CodedInputStream input, ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
Builder builder = newBuilder();
try {
builder.mergeFrom(input);
} catch (InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(builder.buildPartial());
} catch (IOException e) {
throw new InvalidProtocolBufferException(e.getMessage())
.setUnfinishedMessage(builder.buildPartial());
}
return builder.buildPartial();
}
}
private static final Parser PARSER = new Parser();
public final Parser getParserForType() {
return PARSER;
}
}
......@@ -32,6 +32,7 @@ package com.google.protobuf;
import java.util.AbstractList;
import java.util.RandomAccess;
import java.util.List;
import java.util.ListIterator;
import java.util.Iterator;
......@@ -143,4 +144,10 @@ public class UnmodifiableLazyStringList extends AbstractList<String>
}
};
}
@Override
public List<?> getUnderlyingElements() {
// The returned value is already unmodifiable.
return list.getUnderlyingElements();
}
}
This diff is collapsed.
......@@ -146,7 +146,7 @@ public final class WireFormat {
public boolean isPackable() { return true; }
}
// Field numbers for feilds in MessageSet wire format.
// Field numbers for fields in MessageSet wire format.
static final int MESSAGE_SET_ITEM = 1;
static final int MESSAGE_SET_TYPE_ID = 2;
static final int MESSAGE_SET_MESSAGE = 3;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -35,7 +35,7 @@ import junit.framework.TestCase;
/**
* Tests that proto2 api generation doesn't cause compile errors when
* compiling protocol buffers that have names that would otherwise conflict
* if not fully qualified (like @Deprecated and @Override).
* if not fully qualified (like @Deprecated and @Override).
*
* @author jonp@google.com (Jon Perlow)
*/
......@@ -45,5 +45,19 @@ public class TestBadIdentifiers extends TestCase {
// If this compiles, it means the generation was correct.
TestBadIdentifiersProto.Deprecated.newBuilder();
TestBadIdentifiersProto.Override.newBuilder();
}
}
public void testGetDescriptor() {
Descriptors.FileDescriptor fileDescriptor =
TestBadIdentifiersProto.getDescriptor();
String descriptorField = TestBadIdentifiersProto.Descriptor
.getDefaultInstance().getDescriptor();
Descriptors.Descriptor protoDescriptor = TestBadIdentifiersProto.Descriptor
.getDefaultInstance().getDescriptorForType();
String nestedDescriptorField = TestBadIdentifiersProto.Descriptor
.NestedDescriptor.getDefaultInstance().getDescriptor();
Descriptors.Descriptor nestedProtoDescriptor = TestBadIdentifiersProto
.Descriptor.NestedDescriptor.getDefaultInstance()
.getDescriptorForType();
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment