Commit 33165fe0 authored by liujisi@google.com's avatar liujisi@google.com

Submit recent changes from internal branch. See CHANGES.txt for more details.

parent 80aa23df
2010-11-01 version 2.4.0:
General
* The RPC (cc|java|py)_generic_services default value is now false instead of
true.
* Custom options can have aggregate types. For example,
message MyOption {
optional string comment = 1;
optional string author = 2;
}
extend google.protobuf.FieldOptions {
optional MyOption myoption = 12345;
}
This option can now be set as follows:
message SomeType {
optional int32 field = 1 [(myoption) = { comment:'x' author:'y' }];
}
C++
* Various speed and code size optimizations.
* Added a release_foo() method on string and message fields.
* Fixed gzip_output_stream sub-stream handling.
Java
* Builders now maintain sub-builders for sub-messages. Use getFooBuilder() to
get the builder for the sub-message "foo". This allows you to repeatedly
modify deeply-nested sub-messages without rebuilding them.
* Builder.build() no longer invalidates the Builder for generated messages
(You may continue to modify it and then build another message).
* Code generator will generate efficient equals() and hashCode()
implementations if new option java_generate_equals_and_hash is enabled.
(Otherwise, reflection-based implementations are used.)
* Generated messages now implement Serializable.
* Fields with [deprecated=true] will be marked with @Deprecated in Java.
* Added lazy conversion of UTF-8 encoded strings to String objects to improve
performance.
* Various optimizations.
* Enum value can be accessed directly, instead of calling getNumber() on the
enum member.
* For each enum value, an integer constant is also generated with the suffix
_VALUE.
Python
* Added an experimental C++ implementation for Python messages via a Python
extension. Implementation type is controlled by an environment variable
PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION (valid values: "cpp" and "python")
The default value is currently "python" but will be changed to "cpp" in
future release.
* Improved performance on message instantiation significantly.
Most of the work on message instantiation is done just once per message
class, instead of once per message instance.
* Improved performance on text message parsing.
* Allow add() to forward keyword arguments to the concrete class.
E.g. instead of
item = repeated_field.add()
item.foo = bar
item.baz = quux
You can do:
repeated_field.add(foo=bar, baz=quux)
* Added a sort() interface to the BaseContainer.
* Added an extend() method to repeated composite fields.
* Added UTF8 debug string support.
2010-01-08 version 2.3.0:
General
......
......@@ -83,33 +83,57 @@ EXTRA_DIST = \
java/src/main/java/com/google/protobuf/GeneratedMessageLite.java \
java/src/main/java/com/google/protobuf/Internal.java \
java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java \
java/src/main/java/com/google/protobuf/LazyStringArrayList.java \
java/src/main/java/com/google/protobuf/LazyStringList.java \
java/src/main/java/com/google/protobuf/Message.java \
java/src/main/java/com/google/protobuf/MessageLite.java \
java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java \
java/src/main/java/com/google/protobuf/MessageOrBuilder.java \
java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java \
java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java \
java/src/main/java/com/google/protobuf/RpcCallback.java \
java/src/main/java/com/google/protobuf/RpcChannel.java \
java/src/main/java/com/google/protobuf/RpcController.java \
java/src/main/java/com/google/protobuf/RpcUtil.java \
java/src/main/java/com/google/protobuf/Service.java \
java/src/main/java/com/google/protobuf/ServiceException.java \
java/src/main/java/com/google/protobuf/SingleFieldBuilder.java \
java/src/main/java/com/google/protobuf/SmallSortedMap.java \
java/src/main/java/com/google/protobuf/TextFormat.java \
java/src/main/java/com/google/protobuf/UninitializedMessageException.java \
java/src/main/java/com/google/protobuf/UnknownFieldSet.java \
java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java \
java/src/main/java/com/google/protobuf/WireFormat.java \
java/src/test/java/com/google/protobuf/AbstractMessageTest.java \
java/src/test/java/com/google/protobuf/CodedInputStreamTest.java \
java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java \
java/src/test/java/com/google/protobuf/DeprecatedFieldTest.java \
java/src/test/java/com/google/protobuf/DescriptorsTest.java \
java/src/test/java/com/google/protobuf/DynamicMessageTest.java \
java/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java \
java/src/test/java/com/google/protobuf/GeneratedMessageTest.java \
java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java \
java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java \
java/src/test/java/com/google/protobuf/LiteTest.java \
java/src/test/java/com/google/protobuf/MessageTest.java \
java/src/test/java/com/google/protobuf/NestedBuildersTest.java \
java/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java \
java/src/test/java/com/google/protobuf/ServiceTest.java \
java/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java \
java/src/test/java/com/google/protobuf/SmallSortedMapTest.java \
java/src/test/java/com/google/protobuf/TestBadIdentifiers.java \
java/src/test/java/com/google/protobuf/TestUtil.java \
java/src/test/java/com/google/protobuf/TextFormatTest.java \
java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java \
java/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java \
java/src/test/java/com/google/protobuf/WireFormatTest.java \
java/src/test/java/com/google/protobuf/multiple_files_test.proto \
java/src/test/java/com/google/protobuf/nested_builders_test.proto \
java/src/test/java/com/google/protobuf/nested_extension.proto \
java/src/test/java/com/google/protobuf/nested_extension_lite.proto \
java/src/test/java/com/google/protobuf/non_nested_extension.proto \
java/src/test/java/com/google/protobuf/non_nested_extension_lite.proto \
java/src/test/java/com/google/protobuf/test_bad_identifiers.proto \
java/pom.xml \
java/README.txt \
python/google/protobuf/internal/generator_test.py \
......@@ -121,6 +145,9 @@ EXTRA_DIST = \
python/google/protobuf/internal/message_test.py \
python/google/protobuf/internal/more_extensions.proto \
python/google/protobuf/internal/more_messages.proto \
python/google/protobuf/internal/python_message.py \
python/google/protobuf/internal/cpp_message.py \
python/google/protobuf/internal/api_implementation.py \
python/google/protobuf/internal/reflection_test.py \
python/google/protobuf/internal/service_reflection_test.py \
python/google/protobuf/internal/test_util.py \
......@@ -129,6 +156,11 @@ EXTRA_DIST = \
python/google/protobuf/internal/wire_format.py \
python/google/protobuf/internal/wire_format_test.py \
python/google/protobuf/internal/__init__.py \
python/google/protobuf/pyext/python-proto2.cc \
python/google/protobuf/pyext/python_descriptor.cc \
python/google/protobuf/pyext/python_descriptor.h \
python/google/protobuf/pyext/python_protobuf.cc \
python/google/protobuf/pyext/python_protobuf.h \
python/google/protobuf/descriptor.py \
python/google/protobuf/message.py \
python/google/protobuf/reflection.py \
......
......@@ -105,6 +105,12 @@
<arg value="../src/google/protobuf/unittest_mset.proto" />
<arg
value="src/test/java/com/google/protobuf/multiple_files_test.proto" />
<arg value="src/test/java/com/google/protobuf/nested_builders_test.proto" />
<arg value="src/test/java/com/google/protobuf/nested_extension.proto" />
<arg value="src/test/java/com/google/protobuf/nested_extension_lite.proto" />
<arg value="src/test/java/com/google/protobuf/non_nested_extension.proto" />
<arg value="src/test/java/com/google/protobuf/non_nested_extension_lite.proto" />
<arg value="src/test/java/com/google/protobuf/test_bad_identifiers.proto" />
<arg
value="../src/google/protobuf/unittest_optimize_for.proto" />
<arg
......
......@@ -32,9 +32,10 @@ package com.google.protobuf;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Internal.EnumLite;
import java.io.InputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
......@@ -167,11 +168,66 @@ public abstract class AbstractMessage extends AbstractMessageLite
public int hashCode() {
int hash = 41;
hash = (19 * hash) + getDescriptorForType().hashCode();
hash = (53 * hash) + getAllFields().hashCode();
hash = hashFields(hash, getAllFields());
hash = (29 * hash) + getUnknownFields().hashCode();
return hash;
}
/** Get a hash code for given fields and values, using the given seed. */
@SuppressWarnings("unchecked")
protected int hashFields(int hash, Map<FieldDescriptor, Object> map) {
for (Map.Entry<FieldDescriptor, Object> entry : map.entrySet()) {
FieldDescriptor field = entry.getKey();
Object value = entry.getValue();
hash = (37 * hash) + field.getNumber();
if (field.getType() != FieldDescriptor.Type.ENUM){
hash = (53 * hash) + value.hashCode();
} else if (field.isRepeated()) {
List<? extends EnumLite> list = (List<? extends EnumLite>) value;
hash = (53 * hash) + hashEnumList(list);
} else {
hash = (53 * hash) + hashEnum((EnumLite) value);
}
}
return hash;
}
/**
* Helper method for implementing {@link Message#hashCode()}.
* @see Boolean#hashCode()
*/
protected static int hashLong(long n) {
return (int) (n ^ (n >>> 32));
}
/**
* Helper method for implementing {@link Message#hashCode()}.
* @see Boolean#hashCode()
*/
protected static int hashBoolean(boolean b) {
return b ? 1231 : 1237;
}
/**
* Helper method for implementing {@link Message#hashCode()}.
* <p>
* This is needed because {@link java.lang.Enum#hashCode()} is final, but we
* need to use the field number as the hash code to ensure compatibility
* between statically and dynamically generated enum objects.
*/
protected static int hashEnum(EnumLite e) {
return e.getNumber();
}
/** Helper method for implementing {@link Message#hashCode()}. */
protected static int hashEnumList(List<? extends EnumLite> list) {
int hash = 1;
for (EnumLite e : list) {
hash = 31 * hash + hashEnum(e);
}
return hash;
}
// =================================================================
/**
......
......@@ -193,6 +193,18 @@ public final class ByteString {
System.arraycopy(bytes, sourceOffset, target, targetOffset, size);
}
/**
* Copies bytes into a ByteBuffer.
*
* @param target ByteBuffer to copy into.
* @throws ReadOnlyBufferException if the {@code target} is read-only
* @throws BufferOverflowException if the {@code target}'s remaining()
* space is not large enough to hold the data.
*/
public void copyTo(ByteBuffer target) {
target.put(bytes, 0, bytes.length);
}
/**
* Copies bytes to a {@code byte[]}.
*/
......
......@@ -67,7 +67,25 @@ public final class CodedInputStream {
*/
public static CodedInputStream newInstance(final byte[] buf, final int off,
final int len) {
return new CodedInputStream(buf, off, len);
CodedInputStream result = new CodedInputStream(buf, off, len);
try {
// Some uses of CodedInputStream can be more efficient if they know
// exactly how many bytes are available. By pushing the end point of the
// buffer as a limit, we allow them to get this information via
// getBytesUntilLimit(). Pushing a limit that we know is at the end of
// the stream can never hurt, since we can never past that point anyway.
result.pushLimit(len);
} catch (InvalidProtocolBufferException ex) {
// The only reason pushLimit() might throw an exception here is if len
// is negative. Normally pushLimit()'s parameter comes directly off the
// wire, so it's important to catch exceptions in case of corrupt or
// malicious data. However, in this case, we expect that len is not a
// user-supplied value, so we can assume that it being negative indicates
// a programming error. Therefore, throwing an unchecked exception is
// appropriate.
throw new IllegalArgumentException(ex);
}
return result;
}
// -----------------------------------------------------------------
......@@ -263,7 +281,9 @@ public final class CodedInputStream {
/** Read a {@code bytes} field value from the stream. */
public ByteString readBytes() throws IOException {
final int size = readRawVarint32();
if (size <= (bufferSize - bufferPos) && size > 0) {
if (size == 0) {
return ByteString.EMPTY;
} else if (size <= (bufferSize - bufferPos) && size > 0) {
// Fast path: We already have the bytes in a contiguous buffer, so
// just copy directly from it.
final ByteString result = ByteString.copyFrom(buffer, bufferPos, size);
......@@ -368,8 +388,8 @@ public final class CodedInputStream {
* has already read one byte. This allows the caller to determine if EOF
* has been reached before attempting to read.
*/
static int readRawVarint32(final int firstByte,
final InputStream input) throws IOException {
public static int readRawVarint32(
final int firstByte, final InputStream input) throws IOException {
if ((firstByte & 0x80) == 0) {
return firstByte;
}
......@@ -847,19 +867,19 @@ public final class CodedInputStream {
} else {
// Skipping more bytes than are in the buffer. First skip what we have.
int pos = bufferSize - bufferPos;
totalBytesRetired += pos;
bufferPos = 0;
bufferSize = 0;
bufferPos = bufferSize;
// Then skip directly from the InputStream for the rest.
while (pos < size) {
final int n = (input == null) ? -1 : (int) input.skip(size - pos);
if (n <= 0) {
throw InvalidProtocolBufferException.truncatedMessage();
}
pos += n;
totalBytesRetired += n;
// Keep refilling the buffer until we get to the point we wanted to skip
// to. This has the side effect of ensuring the limits are updated
// correctly.
refillBuffer(true);
while (size - pos > bufferSize) {
pos += bufferSize;
bufferPos = bufferSize;
refillBuffer(true);
}
bufferPos = size - pos;
}
}
}
......@@ -33,6 +33,7 @@ package com.google.protobuf;
import java.io.OutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.io.InputStream;
/**
* Encodes and writes protocol message fields.
......@@ -381,9 +382,8 @@ public final class CodedOutputStream {
/** Write a {@code bytes} field to the stream. */
public void writeBytesNoTag(final ByteString value) throws IOException {
final byte[] bytes = value.toByteArray();
writeRawVarint32(bytes.length);
writeRawBytes(bytes);
writeRawVarint32(value.size());
writeRawBytes(value);
}
/** Write a {@code uint32} field to the stream. */
......@@ -870,6 +870,11 @@ public final class CodedOutputStream {
writeRawByte((byte) value);
}
/** Write a byte string. */
public void writeRawBytes(final ByteString value) throws IOException {
writeRawBytes(value, 0, value.size());
}
/** Write an array of bytes. */
public void writeRawBytes(final byte[] value) throws IOException {
writeRawBytes(value, 0, value.length);
......@@ -906,6 +911,53 @@ public final class CodedOutputStream {
}
}
/** Write part of a byte string. */
public void writeRawBytes(final ByteString value, int offset, int length)
throws IOException {
if (limit - position >= length) {
// We have room in the current buffer.
value.copyTo(buffer, offset, position, length);
position += length;
} else {
// Write extends past current buffer. Fill the rest of this buffer and
// flush.
final int bytesWritten = limit - position;
value.copyTo(buffer, offset, position, bytesWritten);
offset += bytesWritten;
length -= bytesWritten;
position = limit;
refreshBuffer();
// Now deal with the rest.
// Since we have an output stream, this is our buffer
// and buffer offset == 0
if (length <= limit) {
// Fits in new buffer.
value.copyTo(buffer, offset, 0, length);
position = length;
} else {
// Write is very big, but we can't do it all at once without allocating
// an a copy of the byte array since ByteString does not give us access
// to the underlying bytes. Use the InputStream interface on the
// ByteString and our buffer to copy between the two.
InputStream inputStreamFrom = value.newInput();
if (offset != inputStreamFrom.skip(offset)) {
throw new IllegalStateException("Skip failed? Should never happen.");
}
// Use the buffer as the temporary buffer to avoid allocating memory.
while (length > 0) {
int bytesToRead = Math.min(length, limit);
int bytesRead = inputStreamFrom.read(buffer, 0, bytesToRead);
if (bytesRead != bytesToRead) {
throw new IllegalStateException("Read failed? Should never happen");
}
output.write(buffer, 0, bytesRead);
length -= bytesRead;
}
}
}
}
/** Encode and write a tag. */
public void writeTag(final int fieldNumber, final int wireType)
throws IOException {
......
......@@ -46,6 +46,11 @@ import java.io.UnsupportedEncodingException;
* its fields and other information about a type. You can get a message
* type's descriptor by calling {@code MessageType.getDescriptor()}, or
* (given a message object of the type) {@code message.getDescriptorForType()}.
* Furthermore, each message is associated with a {@link FileDescriptor} for
* a relevant {@code .proto} file. You can obtain it by calling
* {@code Descriptor.getFile()}. A {@link FileDescriptor} contains descriptors
* for all the messages defined in that file, and file descriptors for all the
* imported {@code .proto} files.
*
* Descriptors are built from DescriptorProtos, as defined in
* {@code google/protobuf/descriptor.proto}.
......@@ -55,6 +60,9 @@ import java.io.UnsupportedEncodingException;
public final class Descriptors {
/**
* Describes a {@code .proto} file, including everything defined within.
* That includes, in particular, descriptors for all the messages and
* file descriptors for all other imported {@code .proto} files
* (dependencies).
*/
public static final class FileDescriptor {
/** Convert the descriptor to its protocol message representation. */
......
......@@ -99,6 +99,91 @@ 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.
*
* @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;
}
/**
* Interface for an enum value or value descriptor, to be used in FieldSet.
* The lite library stores enum values directly in FieldSets but the full
......
// 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.List;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.RandomAccess;
import java.util.Collection;
/**
* An implementation of {@link LazyStringList} that wraps an ArrayList. Each
* element is either a ByteString or a String. It caches the last one requested
* which is most likely the one needed next. This minimizes memory usage while
* satisfying the most common use cases.
* <p>
* <strong>Note that this implementation is not synchronized.</strong>
* If multiple threads access an <tt>ArrayList</tt> instance concurrently,
* and at least one of the threads modifies the list structurally, it
* <i>must</i> be synchronized externally. (A structural modification is
* any operation that adds or deletes one or more elements, or explicitly
* resizes the backing array; merely setting the value of an element is not
* a structural modification.) This is typically accomplished by
* synchronizing on some object that naturally encapsulates the list.
* <p>
* If the implementation is accessed via concurrent reads, this is thread safe.
* Conversions are done in a thread safe manner. It's possible that the
* conversion may happen more than once if two threads attempt to access the
* same element and the modifications were not visible to each other, but this
* will not result in any corruption of the list or change in behavior other
* than performance.
*
* @author jonp@google.com (Jon Perlow)
*/
public class LazyStringArrayList extends AbstractList<String>
implements LazyStringList, RandomAccess {
public final static LazyStringList EMPTY = new UnmodifiableLazyStringList(
new LazyStringArrayList());
private final List<Object> list;
public LazyStringArrayList() {
list = new ArrayList<Object>();
}
public LazyStringArrayList(List<String> from) {
list = new ArrayList<Object>(from);
}
@Override
public String get(int index) {
Object o = list.get(index);
if (o instanceof String) {
return (String) o;
} else {
ByteString bs = (ByteString) o;
String s = bs.toStringUtf8();
if (Internal.isValidUtf8(bs)) {
list.set(index, s);
}
return s;
}
}
@Override
public int size() {
return list.size();
}
@Override
public String set(int index, String s) {
Object o = list.set(index, s);
return asString(o);
}
@Override
public void add(int index, String element) {
list.add(index, element);
modCount++;
}
@Override
public boolean addAll(int index, Collection<? extends String> c) {
boolean ret = list.addAll(index, c);
modCount++;
return ret;
}
@Override
public String remove(int index) {
Object o = list.remove(index);
modCount++;
return asString(o);
}
public void clear() {
list.clear();
modCount++;
}
// @Override
public void add(ByteString element) {
list.add(element);
modCount++;
}
// @Override
public ByteString getByteString(int index) {
Object o = list.get(index);
if (o instanceof String) {
ByteString b = ByteString.copyFromUtf8((String) o);
list.set(index, b);
return b;
} else {
return (ByteString) o;
}
}
private String asString(Object o) {
if (o instanceof String) {
return (String) o;
} else {
return ((ByteString) o).toStringUtf8();
}
}
}
// 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.List;
/**
* An interface extending List&lt;String&gt; 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
* efficiency of serialization if the String was never requested as the
* 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
* through parsing and serialization without conversion to strings. It's not
* attempting to support the functionality of say List&ltByteString&gt, hence
* why only these two very specific methods are added.
*
* @author jonp@google.com (Jon Perlow)
*/
public interface LazyStringList extends List<String> {
/**
* Returns the element at the specified position in this list as a ByteString.
*
* @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>)
*/
ByteString getByteString(int index);
/**
* Appends the specified element to the end of this list (optional
* operation).
*
* @param element element to be appended to this list
* @throws UnsupportedOperationException if the <tt>add</tt> operation
* is not supported by this list
*/
void add(ByteString element);
}
......@@ -48,69 +48,7 @@ import java.util.Map;
*
* @author kenton@google.com Kenton Varda
*/
public interface Message extends MessageLite {
/**
* Get the message's type's descriptor. This differs from the
* {@code getDescriptor()} method of generated message classes in that
* this method is an abstract method of the {@code Message} interface
* whereas {@code getDescriptor()} is a static method of a specific class.
* They return the same thing.
*/
Descriptors.Descriptor getDescriptorForType();
// (From MessageLite, re-declared here only for return type covariance.)
Message getDefaultInstanceForType();
/**
* Returns a collection of all the fields in this message which are set
* and their corresponding values. A singular ("required" or "optional")
* field is set iff hasField() returns true for that field. A "repeated"
* field is set iff getRepeatedFieldSize() is greater than zero. The
* values are exactly what would be returned by calling
* {@link #getField(Descriptors.FieldDescriptor)} for each field. The map
* is guaranteed to be a sorted map, so iterating over it will return fields
* in order by field number.
*/
Map<Descriptors.FieldDescriptor, Object> getAllFields();
/**
* Returns true if the given field is set. This is exactly equivalent to
* calling the generated "has" accessor method corresponding to the field.
* @throws IllegalArgumentException The field is a repeated field, or
* {@code field.getContainingType() != getDescriptorForType()}.
*/
boolean hasField(Descriptors.FieldDescriptor field);
/**
* 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
* embedded message fields, the sub-message is returned. For repeated
* fields, a java.util.List is returned.
*/
Object getField(Descriptors.FieldDescriptor field);
/**
* Gets the number of elements of a repeated field. This is exactly
* equivalent to calling the generated "Count" accessor method corresponding
* to the field.
* @throws IllegalArgumentException The field is not a repeated field, or
* {@code field.getContainingType() != getDescriptorForType()}.
*/
int getRepeatedFieldCount(Descriptors.FieldDescriptor field);
/**
* 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
* is returned.
* @throws IllegalArgumentException The field is not a repeated field, or
* {@code field.getContainingType() != getDescriptorForType()}.
*/
Object getRepeatedField(Descriptors.FieldDescriptor field, int index);
/** Get the {@link UnknownFieldSet} for this message. */
UnknownFieldSet getUnknownFields();
public interface Message extends MessageLite, MessageOrBuilder {
// -----------------------------------------------------------------
// Comparison and hashing
......@@ -119,7 +57,8 @@ public interface Message extends MessageLite {
* 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
* defined by {@code getDescriptorForType()}) and has identical values for
* all of its fields.
* 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
......@@ -129,8 +68,9 @@ public interface Message extends MessageLite {
/**
* Returns the hash code value for this message. The hash code of a message
* is defined to be <tt>getDescriptor().hashCode() ^ map.hashCode()</tt>,
* where <tt>map</tt> is a map of field numbers to field values.
* should mix the message's type (object identity of the decsriptor) with its
* contents (known and unknown field values). Subclasses must implement this;
* inheriting {@code Object.hashCode()} is incorrect.
*
* @return the hash code value for this message
* @see Map#hashCode()
......@@ -158,7 +98,7 @@ public interface Message extends MessageLite {
/**
* Abstract interface implemented by Protocol Message builders.
*/
interface Builder extends MessageLite.Builder {
interface Builder extends MessageLite.Builder, MessageOrBuilder {
// (From MessageLite.Builder, re-declared here only for return type
// covariance.)
Builder clear();
......@@ -197,17 +137,6 @@ public interface Message extends MessageLite {
*/
Descriptors.Descriptor getDescriptorForType();
// (From MessageLite.Builder, re-declared here only for return type
// covariance.)
Message getDefaultInstanceForType();
/**
* Like {@link Message#getAllFields()}. The returned map may or may not
* reflect future changes to the builder. Either way, the returned map is
* itself unmodifiable.
*/
Map<Descriptors.FieldDescriptor, Object> getAllFields();
/**
* Create a Builder for messages of the appropriate type for the given
* field. Messages built with this can then be passed to setField(),
......@@ -215,12 +144,6 @@ public interface Message extends MessageLite {
*/
Builder newBuilderForField(Descriptors.FieldDescriptor field);
/** Like {@link Message#hasField(Descriptors.FieldDescriptor)} */
boolean hasField(Descriptors.FieldDescriptor field);
/** Like {@link Message#getField(Descriptors.FieldDescriptor)} */
Object getField(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
......@@ -234,16 +157,6 @@ public interface Message extends MessageLite {
*/
Builder clearField(Descriptors.FieldDescriptor field);
/**
* Like {@link Message#getRepeatedFieldCount(Descriptors.FieldDescriptor)}
*/
int getRepeatedFieldCount(Descriptors.FieldDescriptor field);
/**
* Like {@link Message#getRepeatedField(Descriptors.FieldDescriptor,int)}
*/
Object getRepeatedField(Descriptors.FieldDescriptor field, int index);
/**
* Sets an element of a repeated field to the given value. The value must
* be of the correct type for this field, i.e. the same type that
......@@ -262,9 +175,6 @@ public interface Message extends MessageLite {
*/
Builder addRepeatedField(Descriptors.FieldDescriptor field, Object value);
/** Get the {@link UnknownFieldSet} for this message. */
UnknownFieldSet getUnknownFields();
/** Set the {@link UnknownFieldSet} for this message. */
Builder setUnknownFields(UnknownFieldSet unknownFields);
......
......@@ -64,22 +64,8 @@ import java.io.OutputStream;
*
* @author kenton@google.com Kenton Varda
*/
public interface MessageLite {
/**
* Get an instance of the type with all fields set to their default values.
* This may or may not be a singleton. This differs from the
* {@code getDefaultInstance()} method of generated message classes in that
* this method is an abstract method of the {@code MessageLite} interface
* whereas {@code getDefaultInstance()} is a static method of a specific
* class. They return the same thing.
*/
MessageLite getDefaultInstanceForType();
public interface MessageLite extends MessageLiteOrBuilder {
/**
* Returns true if all required fields in the message and all embedded
* messages are set, false otherwise.
*/
boolean isInitialized();
/**
* Serializes the message and writes it to {@code output}. This does not
......@@ -153,7 +139,7 @@ public interface MessageLite {
/**
* Abstract interface implemented by Protocol Message builders.
*/
interface Builder extends Cloneable {
interface Builder extends MessageLiteOrBuilder, Cloneable {
/** Resets all fields to their default values. */
Builder clear();
......@@ -186,12 +172,6 @@ public interface MessageLite {
*/
Builder clone();
/**
* Returns true if all required fields in the message and all embedded
* messages are set, false otherwise.
*/
boolean isInitialized();
/**
* Parses a message of this type from the input and merges it with this
* message, as if using {@link Builder#mergeFrom(MessageLite)}.
......@@ -230,12 +210,6 @@ public interface MessageLite {
ExtensionRegistryLite extensionRegistry)
throws IOException;
/**
* Get the message's type's default instance.
* See {@link MessageLite#getDefaultInstanceForType()}.
*/
MessageLite getDefaultInstanceForType();
// ---------------------------------------------------------------
// Convenience methods.
......@@ -243,6 +217,8 @@ public interface MessageLite {
* 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)}.
*
* @return this
*/
Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException;
......@@ -250,6 +226,8 @@ public interface MessageLite {
* 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)}.
*
* @return this
*/
Builder mergeFrom(ByteString data,
ExtensionRegistryLite extensionRegistry)
......@@ -259,6 +237,8 @@ public interface MessageLite {
* 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)}.
*
* @return this
*/
Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException;
......@@ -266,6 +246,8 @@ public interface MessageLite {
* 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)}.
*
* @return this
*/
Builder mergeFrom(byte[] data, int off, int len)
throws InvalidProtocolBufferException;
......@@ -274,6 +256,8 @@ public interface MessageLite {
* 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)}.
*
* @return this
*/
Builder mergeFrom(byte[] data,
ExtensionRegistryLite extensionRegistry)
......@@ -283,6 +267,8 @@ public interface MessageLite {
* 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)}.
*
* @return this
*/
Builder mergeFrom(byte[] data, int off, int len,
ExtensionRegistryLite extensionRegistry)
......@@ -299,6 +285,8 @@ public interface MessageLite {
* and {@link #mergeDelimitedFrom(InputStream)} to read it.
* <p>
* Despite usually reading the entire input, this does not close the stream.
*
* @return this
*/
Builder mergeFrom(InputStream input) throws IOException;
......@@ -306,6 +294,8 @@ public interface MessageLite {
* 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)}.
*
* @return this
*/
Builder mergeFrom(InputStream input,
ExtensionRegistryLite extensionRegistry)
......
// 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;
/**
* Base interface for methods common to {@link MessageLite}
* and {@link MessageLite.Builder} to provide type equivalency.
*
* @author jonp@google.com (Jon Perlow)
*/
public interface MessageLiteOrBuilder {
/**
* Get an instance of the type with all fields set to their default values.
* This may or may not be a singleton. This differs from the
* {@code getDefaultInstance()} method of generated message classes in that
* this method is an abstract method of the {@code MessageLite} interface
* whereas {@code getDefaultInstance()} is a static method of a specific
* class. They return the same thing.
*/
MessageLite getDefaultInstanceForType();
/**
* Returns true if all required fields in the message and all embedded
* messages are set, false otherwise.
*/
boolean isInitialized();
}
// 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.Map;
/**
* Base interface for methods common to {@link Message} and
* {@link Message.Builder} to provide type equivalency.
*
* @author jonp@google.com (Jon Perlow)
*/
public interface MessageOrBuilder extends MessageLiteOrBuilder {
// (From MessageLite, re-declared here only for return type covariance.)
//@Override (Java 1.6 override semantics, but we must support 1.5)
Message getDefaultInstanceForType();
/**
* Get the message's type's descriptor. This differs from the
* {@code getDescriptor()} method of generated message classes in that
* this method is an abstract method of the {@code Message} interface
* whereas {@code getDescriptor()} is a static method of a specific class.
* They return the same thing.
*/
Descriptors.Descriptor getDescriptorForType();
/**
* Returns a collection of all the fields in this message which are set
* and their corresponding values. A singular ("required" or "optional")
* field is set iff hasField() returns true for that field. A "repeated"
* field is set iff getRepeatedFieldSize() is greater than zero. The
* values are exactly what would be returned by calling
* {@link #getField(Descriptors.FieldDescriptor)} for each field. The map
* is guaranteed to be a sorted map, so iterating over it will return fields
* in order by field number.
* <br>
* If this is for a builder, the returned map may or may not reflect future
* changes to the builder. Either way, the returned map is itself
* unmodifiable.
*/
Map<Descriptors.FieldDescriptor, Object> getAllFields();
/**
* Returns true if the given field is set. This is exactly equivalent to
* calling the generated "has" accessor method corresponding to the field.
* @throws IllegalArgumentException The field is a repeated field, or
* {@code field.getContainingType() != getDescriptorForType()}.
*/
boolean hasField(Descriptors.FieldDescriptor field);
/**
* 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
* embedded message fields, the sub-message is returned. For repeated
* fields, a java.util.List is returned.
*/
Object getField(Descriptors.FieldDescriptor field);
/**
* Gets the number of elements of a repeated field. This is exactly
* equivalent to calling the generated "Count" accessor method corresponding
* to the field.
* @throws IllegalArgumentException The field is not a repeated field, or
* {@code field.getContainingType() != getDescriptorForType()}.
*/
int getRepeatedFieldCount(Descriptors.FieldDescriptor field);
/**
* 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
* is returned.
* @throws IllegalArgumentException The field is not a repeated field, or
* {@code field.getContainingType() != getDescriptorForType()}.
*/
Object getRepeatedField(Descriptors.FieldDescriptor field, int index);
/** Get the {@link UnknownFieldSet} for this message. */
UnknownFieldSet getUnknownFields();
}
......@@ -35,10 +35,18 @@ package com.google.protobuf;
*
* @author cpovirk@google.com (Chris Povirk)
*/
public final class ServiceException extends Exception {
public class ServiceException extends Exception {
private static final long serialVersionUID = -1219262335729891920L;
public ServiceException(final String message) {
super(message);
}
public ServiceException(final Throwable cause) {
super(cause);
}
public ServiceException(final String message, final Throwable cause) {
super(message, cause);
}
}
// 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;
/**
* <code>SingleFieldBuilder</code> 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
* 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>
* 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.
*
* @param <MType> the type of message for the field
* @param <BType> the type of builder for the field
* @param <IType> the common interface for the message and the builder
*
* @author jonp@google.com (Jon Perlow)
*/
public class SingleFieldBuilder
<MType extends GeneratedMessage,
BType extends GeneratedMessage.Builder,
IType extends MessageOrBuilder>
implements GeneratedMessage.BuilderParent {
// Parent to send changes to.
private GeneratedMessage.BuilderParent parent;
// Invariant: one of builder or message fields must be non-null.
// If set, this is the case where we are backed by a builder. In this case,
// message field represents a cached message for the builder (or null if
// there is no cached message).
private BType builder;
// If builder is non-null, this represents a cached message from the builder.
// If builder is null, this is the authoritative message for the field.
private MType message;
// Indicates that we've built a message and so we are now obligated
// to dispatch dirty invalidations. See GeneratedMessage.BuilderListener.
private boolean isClean;
public SingleFieldBuilder(
MType message,
GeneratedMessage.BuilderParent parent,
boolean isClean) {
if (message == null) {
throw new NullPointerException();
}
this.message = message;
this.parent = parent;
this.isClean = isClean;
}
public void dispose() {
// Null out parent so we stop sending it invalidations.
parent = null;
}
/**
* 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
* calling {@link Message.Builder#buildPartial} on it. If no message has
* been set, returns the default instance of the message.
*
* @return the message for the field
*/
@SuppressWarnings("unchecked")
public MType getMessage() {
if (message == null) {
// If message is null, the invariant is that we must be have a builder.
message = (MType) builder.buildPartial();
}
return message;
}
/**
* Builds the message and returns it.
*
* @return the message
*/
public MType build() {
// Now that build has been called, we are required to dispatch
// invalidations.
isClean = true;
return getMessage();
}
/**
* Gets a builder for the field. If no builder has been created yet, a
* builder is created on demand by calling {@link Message#toBuilder}.
*
* @return The builder for the field
*/
@SuppressWarnings("unchecked")
public BType getBuilder() {
if (builder == null) {
// builder.mergeFrom() on a fresh builder
// does not create any sub-objects with independent clean/dirty states,
// therefore setting the builder itself to clean without actually calling
// build() cannot break any invariants.
builder = (BType) message.newBuilderForType(this);
builder.mergeFrom(message); // no-op if message is the default message
builder.markClean();
}
return builder;
}
/**
* Gets the base class interface for the field. This may either be a builder
* or a message. It will return whatever is more efficient.
*
* @return the message or builder for the field as the base class interface
*/
@SuppressWarnings("unchecked")
public IType getMessageOrBuilder() {
if (builder != null) {
return (IType) builder;
} else {
return (IType) message;
}
}
/**
* Sets a message for the field replacing any existing value.
*
* @param message the message to set
* @return the builder
*/
public SingleFieldBuilder<MType, BType, IType> setMessage(
MType message) {
if (message == null) {
throw new NullPointerException();
}
this.message = message;
if (builder != null) {
builder.dispose();
builder = null;
}
onChanged();
return this;
}
/**
* Merges the field from another field.
*
* @param value the value to merge from
* @return the builder
*/
public SingleFieldBuilder<MType, BType, IType> mergeFrom(
MType value) {
if (builder == null && message == message.getDefaultInstanceForType()) {
message = value;
} else {
getBuilder().mergeFrom(value);
}
onChanged();
return this;
}
/**
* Clears the value of the field.
*
* @return the builder
*/
@SuppressWarnings("unchecked")
public SingleFieldBuilder<MType, BType, IType> clear() {
message = (MType) (message != null ?
message.getDefaultInstanceForType() :
builder.getDefaultInstanceForType());
if (builder != null) {
builder.dispose();
builder = null;
}
onChanged();
return this;
}
/**
* Called when a the builder or one of its nested children has changed
* and any parent should be notified of its invalidation.
*/
private void onChanged() {
// If builder is null, this is the case where onChanged is being called
// from setMessage or clear.
if (builder != null) {
message = null;
}
if (isClean && parent != null) {
parent.markDirty();
// Don't keep dispatching invalidations until build is called again.
isClean = false;
}
}
@Override
public void markDirty() {
onChanged();
}
}
This diff is collapsed.
// 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.AbstractList;
import java.util.RandomAccess;
import java.util.ListIterator;
import java.util.Iterator;
/**
* An implementation of {@link LazyStringList} that wraps another
* {@link LazyStringList} such that it cannot be modified via the wrapper.
*
* @author jonp@google.com (Jon Perlow)
*/
public class UnmodifiableLazyStringList extends AbstractList<String>
implements LazyStringList, RandomAccess {
private final LazyStringList list;
public UnmodifiableLazyStringList(LazyStringList list) {
this.list = list;
}
@Override
public String get(int index) {
return list.get(index);
}
@Override
public int size() {
return list.size();
}
@Override
public ByteString getByteString(int index) {
return list.getByteString(index);
}
@Override
public void add(ByteString element) {
throw new UnsupportedOperationException();
}
@Override
public ListIterator<String> listIterator(final int index) {
return new ListIterator<String>() {
ListIterator<String> iter = list.listIterator(index);
@Override
public boolean hasNext() {
return iter.hasNext();
}
@Override
public String next() {
return iter.next();
}
@Override
public boolean hasPrevious() {
return iter.hasPrevious();
}
@Override
public String previous() {
return iter.previous();
}
@Override
public int nextIndex() {
return iter.nextIndex();
}
@Override
public int previousIndex() {
return iter.previousIndex();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
@Override
public void set(String o) {
throw new UnsupportedOperationException();
}
@Override
public void add(String o) {
throw new UnsupportedOperationException();
}
};
}
@Override
public Iterator<String> iterator() {
return new Iterator<String>() {
Iterator<String> iter = list.iterator();
@Override
public boolean hasNext() {
return iter.hasNext();
}
@Override
public String next() {
return iter.next();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}
......@@ -45,12 +45,12 @@ public final class WireFormat {
// Do not allow instantiation.
private WireFormat() {}
static final int WIRETYPE_VARINT = 0;
static final int WIRETYPE_FIXED64 = 1;
static final int WIRETYPE_LENGTH_DELIMITED = 2;
static final int WIRETYPE_START_GROUP = 3;
static final int WIRETYPE_END_GROUP = 4;
static final int WIRETYPE_FIXED32 = 5;
public static final int WIRETYPE_VARINT = 0;
public static final int WIRETYPE_FIXED64 = 1;
public static final int WIRETYPE_LENGTH_DELIMITED = 2;
public static final int WIRETYPE_START_GROUP = 3;
public static final int WIRETYPE_END_GROUP = 4;
public static final int WIRETYPE_FIXED32 = 5;
static final int TAG_TYPE_BITS = 3;
static final int TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1;
......
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