aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar kenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2009-01-22 01:27:00 +0000
committerGravatar kenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2009-01-22 01:27:00 +0000
commit2d6daa72ab5832bf4cab38df0d911f32df547021 (patch)
tree5f9304a6ff2c7c0cb7ed62eead92bf05411666f8
parent87e64e1ceeff224043078e7e31fe0b1a119c8b1a (diff)
Push out changes from internal codebase.
All Languages * Repeated fields of primitive types (types other that string, group, and nested messages) may now use the option [packed = true] to get a more efficient encoding. In the new encoding, the entire list is written as a single byte blob using the "length-delimited" wire type. Within this blob, the individual values are encoded the same way they would be normally except without a tag before each value (thus, they are tightly "packed"). C++ * UnknownFieldSet now supports STL-like iteration. * Message interface has method ParseFromBoundedZeroCopyStream() which parses a limited number of bytes from an input stream rather than parsing until EOF. Java * Fixed bug where Message.mergeFrom(Message) failed to merge extensions. * Message interface has new method toBuilder() which is equivalent to newBuilderForType().mergeFrom(this). * All enums now implement the ProtocolMessageEnum interface. * Setting a field to null now throws NullPointerException. * Fixed tendency for TextFormat's parsing to overflow the stack when parsing large string values. The underlying problem is with Java's regex implementation (which unfortunately uses recursive backtracking rather than building an NFA). Worked around by making use of possesive quantifiers. Python * Updated RPC interfaces to allow for blocking operation. A client may now pass None for a callback when making an RPC, in which case the call will block until the response is received, and the response object will be returned directly to the caller. This interface change cannot be used in practice until RPC implementations are updated to implement it.
-rw-r--r--CHANGES.txt35
-rw-r--r--Makefile.am1
-rw-r--r--java/src/main/java/com/google/protobuf/AbstractMessage.java43
-rw-r--r--java/src/main/java/com/google/protobuf/CodedInputStream.java15
-rw-r--r--java/src/main/java/com/google/protobuf/CodedOutputStream.java507
-rw-r--r--java/src/main/java/com/google/protobuf/Descriptors.java13
-rw-r--r--java/src/main/java/com/google/protobuf/DynamicMessage.java5
-rw-r--r--java/src/main/java/com/google/protobuf/FieldSet.java154
-rw-r--r--java/src/main/java/com/google/protobuf/GeneratedMessage.java102
-rw-r--r--java/src/main/java/com/google/protobuf/Message.java6
-rw-r--r--java/src/main/java/com/google/protobuf/TextFormat.java12
-rw-r--r--java/src/main/java/com/google/protobuf/WireFormat.java10
-rw-r--r--java/src/test/java/com/google/protobuf/AbstractMessageTest.java23
-rw-r--r--java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java11
-rw-r--r--java/src/test/java/com/google/protobuf/DynamicMessageTest.java68
-rw-r--r--java/src/test/java/com/google/protobuf/GeneratedMessageTest.java198
-rw-r--r--java/src/test/java/com/google/protobuf/TestUtil.java1518
-rw-r--r--java/src/test/java/com/google/protobuf/TextFormatTest.java28
-rw-r--r--java/src/test/java/com/google/protobuf/WireFormatTest.java49
-rwxr-xr-xpython/google/protobuf/internal/containers.py13
-rwxr-xr-xpython/google/protobuf/internal/decoder_test.py2
-rwxr-xr-xpython/google/protobuf/internal/encoder.py140
-rwxr-xr-xpython/google/protobuf/internal/encoder_test.py70
-rwxr-xr-xpython/google/protobuf/internal/reflection_test.py120
-rwxr-xr-xpython/google/protobuf/internal/service_reflection_test.py6
-rwxr-xr-xpython/google/protobuf/internal/test_util.py48
-rwxr-xr-xpython/google/protobuf/internal/type_checkers.py17
-rwxr-xr-xpython/google/protobuf/internal/wire_format.py35
-rwxr-xr-xpython/google/protobuf/reflection.py99
-rwxr-xr-xpython/google/protobuf/service.py17
-rwxr-xr-xpython/google/protobuf/service_reflection.py23
-rw-r--r--src/Makefile.am1
-rw-r--r--src/google/protobuf/compiler/command_line_interface.cc3
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum_field.cc91
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc25
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.cc10
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_primitive_field.cc82
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.cc10
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto8
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_unittest.cc8
-rw-r--r--src/google/protobuf/compiler/java/java_enum.cc3
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field.cc86
-rw-r--r--src/google/protobuf/compiler/java/java_message.cc12
-rw-r--r--src/google/protobuf/compiler/java/java_message_field.cc9
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field.cc155
-rw-r--r--src/google/protobuf/compiler/python/python_generator.cc1
-rw-r--r--src/google/protobuf/descriptor.cc344
-rw-r--r--src/google/protobuf/descriptor.h50
-rw-r--r--src/google/protobuf/descriptor.pb.cc211
-rw-r--r--src/google/protobuf/descriptor.pb.h37
-rw-r--r--src/google/protobuf/descriptor.proto6
-rw-r--r--src/google/protobuf/descriptor_unittest.cc245
-rw-r--r--src/google/protobuf/dynamic_message_unittest.cc16
-rw-r--r--src/google/protobuf/extension_set_unittest.cc25
-rw-r--r--src/google/protobuf/io/coded_stream.cc28
-rw-r--r--src/google/protobuf/io/coded_stream.h28
-rw-r--r--src/google/protobuf/io/coded_stream_unittest.cc70
-rw-r--r--src/google/protobuf/message.cc26
-rw-r--r--src/google/protobuf/message.h8
-rw-r--r--src/google/protobuf/message_unittest.cc32
-rw-r--r--src/google/protobuf/test_util.cc479
-rw-r--r--src/google/protobuf/test_util.h25
-rw-r--r--src/google/protobuf/unittest.proto40
-rw-r--r--src/google/protobuf/unknown_field_set.cc40
-rw-r--r--src/google/protobuf/unknown_field_set.h152
-rw-r--r--src/google/protobuf/unknown_field_set_unittest.cc86
-rw-r--r--src/google/protobuf/wire_format.cc316
-rw-r--r--src/google/protobuf/wire_format.h42
-rw-r--r--src/google/protobuf/wire_format_inl.h100
-rw-r--r--src/google/protobuf/wire_format_unittest.cc55
70 files changed, 5088 insertions, 1265 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 7cc10e12..2a86a63c 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,8 +1,41 @@
-version 2.0.4:
+????-??-?? version 2.0.4:
+
+ General
+ * Repeated fields of primitive types (types other that string, group, and
+ nested messages) may now use the option [packed = true] to get a more
+ efficient encoding. In the new encoding, the entire list is written
+ as a single byte blob using the "length-delimited" wire type. Within
+ this blob, the individual values are encoded the same way they would
+ be normally except without a tag before each value (thus, they are
+ tightly "packed").
+
+ C++
+ * UnknownFieldSet now supports STL-like iteration.
+ * Message interface has method ParseFromBoundedZeroCopyStream() which parses
+ a limited number of bytes from an input stream rather than parsing until
+ EOF.
+
+ Java
+ * Fixed bug where Message.mergeFrom(Message) failed to merge extensions.
+ * Message interface has new method toBuilder() which is equivalent to
+ newBuilderForType().mergeFrom(this).
+ * All enums now implement the ProtocolMessageEnum interface.
+ * Setting a field to null now throws NullPointerException.
+ * Fixed tendency for TextFormat's parsing to overflow the stack when
+ parsing large string values. The underlying problem is with Java's
+ regex implementation (which unfortunately uses recursive backtracking
+ rather than building an NFA). Worked around by making use of possesive
+ quantifiers.
Python
* Added slicing support for repeated scalar fields. Added slice retrieval and
removal of repeated composite fields.
+ * Updated RPC interfaces to allow for blocking operation. A client may
+ now pass None for a callback when making an RPC, in which case the
+ call will block until the response is received, and the response
+ object will be returned directly to the caller. This interface change
+ cannot be used in practice until RPC implementations are updated to
+ implement it.
2008-11-25 version 2.0.3:
diff --git a/Makefile.am b/Makefile.am
index c3d40b1f..b4ceacd4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -45,6 +45,7 @@ EXTRA_DIST = \
java/src/main/java/com/google/protobuf/GeneratedMessage.java \
java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java \
java/src/main/java/com/google/protobuf/Message.java \
+ java/src/main/java/com/google/protobuf/ProtocolMessageEnum.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 \
diff --git a/java/src/main/java/com/google/protobuf/AbstractMessage.java b/java/src/main/java/com/google/protobuf/AbstractMessage.java
index 2f61859d..24c32a47 100644
--- a/java/src/main/java/com/google/protobuf/AbstractMessage.java
+++ b/java/src/main/java/com/google/protobuf/AbstractMessage.java
@@ -86,8 +86,25 @@ public abstract class AbstractMessage implements Message {
for (Map.Entry<FieldDescriptor, Object> entry : getAllFields().entrySet()) {
FieldDescriptor field = entry.getKey();
if (field.isRepeated()) {
- for (Object element : (List) entry.getValue()) {
- output.writeField(field.getType(), field.getNumber(), element);
+ List valueList = (List) entry.getValue();
+ if (field.getOptions().getPacked()) {
+
+ output.writeTag(field.getNumber(),
+ WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ int dataSize = 0;
+ for (Object element : valueList) {
+ dataSize += CodedOutputStream.computeFieldSizeNoTag(
+ field.getType(), element);
+ }
+ output.writeRawVarint32(dataSize);
+
+ for (Object element : valueList) {
+ output.writeFieldNoTag(field.getType(), element);
+ }
+ } else {
+ for (Object element : valueList) {
+ output.writeField(field.getType(), field.getNumber(), element);
+ }
}
} else {
output.writeField(field.getType(), field.getNumber(), entry.getValue());
@@ -145,9 +162,21 @@ public abstract class AbstractMessage implements Message {
for (Map.Entry<FieldDescriptor, Object> entry : getAllFields().entrySet()) {
FieldDescriptor field = entry.getKey();
if (field.isRepeated()) {
- for (Object element : (List) entry.getValue()) {
- size += CodedOutputStream.computeFieldSize(
- field.getType(), field.getNumber(), element);
+ List valueList = (List) entry.getValue();
+ if (field.getOptions().getPacked()) {
+ int dataSize = 0;
+ for (Object element : valueList) {
+ dataSize += CodedOutputStream.computeFieldSizeNoTag(
+ field.getType(), element);
+ }
+ size += dataSize;
+ size += CodedOutputStream.computeTagSize(field.getNumber());
+ size += CodedOutputStream.computeRawVarint32Size(dataSize);
+ } else {
+ for (Object element : valueList) {
+ size += CodedOutputStream.computeFieldSize(
+ field.getType(), field.getNumber(), element);
+ }
}
} else {
size += CodedOutputStream.computeFieldSize(
@@ -165,7 +194,7 @@ public abstract class AbstractMessage implements Message {
memoizedSize = size;
return size;
}
-
+
@Override
public boolean equals(Object other) {
if (other == this) {
@@ -180,7 +209,7 @@ public abstract class AbstractMessage implements Message {
}
return getAllFields().equals(otherMessage.getAllFields());
}
-
+
@Override
public int hashCode() {
int hash = 41;
diff --git a/java/src/main/java/com/google/protobuf/CodedInputStream.java b/java/src/main/java/com/google/protobuf/CodedInputStream.java
index caef068b..8f277a9f 100644
--- a/java/src/main/java/com/google/protobuf/CodedInputStream.java
+++ b/java/src/main/java/com/google/protobuf/CodedInputStream.java
@@ -193,7 +193,7 @@ public final class CodedInputStream {
/** Read a {@code string} field value from the stream. */
public String readString() throws IOException {
int size = readRawVarint32();
- if (size < bufferSize - bufferPos && size > 0) {
+ if (size <= (bufferSize - bufferPos) && size > 0) {
// Fast path: We already have the bytes in a contiguous buffer, so
// just copy directly from it.
String result = new String(buffer, bufferPos, size, "UTF-8");
@@ -584,6 +584,19 @@ public final class CodedInputStream {
}
/**
+ * Returns the number of bytes to be read before the current limit.
+ * If no limit is set, returns -1.
+ */
+ public int getBytesUntilLimit() {
+ if (currentLimit == Integer.MAX_VALUE) {
+ return -1;
+ }
+
+ int currentAbsolutePosition = totalBytesRetired + bufferPos;
+ return currentLimit - currentAbsolutePosition;
+ }
+
+ /**
* Called with {@code this.buffer} is empty to read more bytes from the
* input. If {@code mustSucceed} is true, refillBuffer() gurantees that
* either there will be at least one byte in the buffer when it returns
diff --git a/java/src/main/java/com/google/protobuf/CodedOutputStream.java b/java/src/main/java/com/google/protobuf/CodedOutputStream.java
index d232841a..e8be8611 100644
--- a/java/src/main/java/com/google/protobuf/CodedOutputStream.java
+++ b/java/src/main/java/com/google/protobuf/CodedOutputStream.java
@@ -118,71 +118,61 @@ public final class CodedOutputStream {
/** Write a {@code double} field, including tag, to the stream. */
public void writeDouble(int fieldNumber, double value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
- writeRawLittleEndian64(Double.doubleToRawLongBits(value));
+ writeDoubleNoTag(value);
}
/** Write a {@code float} field, including tag, to the stream. */
public void writeFloat(int fieldNumber, float value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
- writeRawLittleEndian32(Float.floatToRawIntBits(value));
+ writeFloatNoTag(value);
}
/** Write a {@code uint64} field, including tag, to the stream. */
public void writeUInt64(int fieldNumber, long value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- writeRawVarint64(value);
+ writeUInt64NoTag(value);
}
/** Write an {@code int64} field, including tag, to the stream. */
public void writeInt64(int fieldNumber, long value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- writeRawVarint64(value);
+ writeInt64NoTag(value);
}
/** Write an {@code int32} field, including tag, to the stream. */
public void writeInt32(int fieldNumber, int value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- if (value >= 0) {
- writeRawVarint32(value);
- } else {
- // Must sign-extend.
- writeRawVarint64(value);
- }
+ writeInt32NoTag(value);
}
/** Write a {@code fixed64} field, including tag, to the stream. */
public void writeFixed64(int fieldNumber, long value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
- writeRawLittleEndian64(value);
+ writeFixed64NoTag(value);
}
/** Write a {@code fixed32} field, including tag, to the stream. */
public void writeFixed32(int fieldNumber, int value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
- writeRawLittleEndian32(value);
+ writeFixed32NoTag(value);
}
/** Write a {@code bool} field, including tag, to the stream. */
public void writeBool(int fieldNumber, boolean value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- writeRawByte(value ? 1 : 0);
+ writeBoolNoTag(value);
}
/** Write a {@code string} field, including tag, to the stream. */
public void writeString(int fieldNumber, String value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
- // Unfortunately there does not appear to be any way to tell Java to encode
- // UTF-8 directly into our buffer, so we have to let it create its own byte
- // array and then copy.
- byte[] bytes = value.getBytes("UTF-8");
- writeRawVarint32(bytes.length);
- writeRawBytes(bytes);
+ writeStringNoTag(value);
}
/** Write a {@code group} field, including tag, to the stream. */
public void writeGroup(int fieldNumber, Message value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
- value.writeTo(this);
+ writeGroupNoTag(value);
writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
}
@@ -190,29 +180,26 @@ public final class CodedOutputStream {
public void writeUnknownGroup(int fieldNumber, UnknownFieldSet value)
throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
- value.writeTo(this);
+ writeUnknownGroupNoTag(value);
writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
}
/** Write an embedded message field, including tag, to the stream. */
public void writeMessage(int fieldNumber, Message value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
- writeRawVarint32(value.getSerializedSize());
- value.writeTo(this);
+ writeMessageNoTag(value);
}
/** Write a {@code bytes} field, including tag, to the stream. */
public void writeBytes(int fieldNumber, ByteString value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
- byte[] bytes = value.toByteArray();
- writeRawVarint32(bytes.length);
- writeRawBytes(bytes);
+ writeBytesNoTag(value);
}
/** Write a {@code uint32} field, including tag, to the stream. */
public void writeUInt32(int fieldNumber, int value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- writeRawVarint32(value);
+ writeUInt32NoTag(value);
}
/**
@@ -221,31 +208,31 @@ public final class CodedOutputStream {
*/
public void writeEnum(int fieldNumber, int value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- writeRawVarint32(value);
+ writeEnumNoTag(value);
}
/** Write an {@code sfixed32} field, including tag, to the stream. */
public void writeSFixed32(int fieldNumber, int value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
- writeRawLittleEndian32(value);
+ writeSFixed32NoTag(value);
}
/** Write an {@code sfixed64} field, including tag, to the stream. */
public void writeSFixed64(int fieldNumber, long value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
- writeRawLittleEndian64(value);
+ writeSFixed64NoTag(value);
}
/** Write an {@code sint32} field, including tag, to the stream. */
public void writeSInt32(int fieldNumber, int value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- writeRawVarint32(encodeZigZag32(value));
+ writeSInt32NoTag(value);
}
/** Write an {@code sint64} field, including tag, to the stream. */
public void writeSInt64(int fieldNumber, long value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- writeRawVarint64(encodeZigZag64(value));
+ writeSInt64NoTag(value);
}
/**
@@ -283,32 +270,168 @@ public final class CodedOutputStream {
* this field.
*/
public void writeField(Descriptors.FieldDescriptor.Type type,
- int number, Object value) throws IOException {
+ int number,
+ Object value) throws IOException {
+ // Special case for groups, which need a start and end tag; other fields
+ // can just use writeTag() and writeFieldNoTag().
+ if (type == Descriptors.FieldDescriptor.Type.GROUP) {
+ writeGroup(number, (Message) value);
+ } else {
+ writeTag(number, WireFormat.getWireFormatForFieldType(type));
+ writeFieldNoTag(type, value);
+ }
+ }
+
+ /**
+ * Write a field of arbitrary type, without its tag, to the stream.
+ *
+ * @param type The field's type.
+ * @param value Object representing the field's value. Must be of the exact
+ * type which would be returned by
+ * {@link Message#getField(Descriptors.FieldDescriptor)} for
+ * this field.
+ */
+ public void writeFieldNoTag(Descriptors.FieldDescriptor.Type type,
+ Object value) throws IOException {
switch (type) {
- case DOUBLE : writeDouble (number, (Double )value); break;
- case FLOAT : writeFloat (number, (Float )value); break;
- case INT64 : writeInt64 (number, (Long )value); break;
- case UINT64 : writeUInt64 (number, (Long )value); break;
- case INT32 : writeInt32 (number, (Integer )value); break;
- case FIXED64 : writeFixed64 (number, (Long )value); break;
- case FIXED32 : writeFixed32 (number, (Integer )value); break;
- case BOOL : writeBool (number, (Boolean )value); break;
- case STRING : writeString (number, (String )value); break;
- case GROUP : writeGroup (number, (Message )value); break;
- case MESSAGE : writeMessage (number, (Message )value); break;
- case BYTES : writeBytes (number, (ByteString)value); break;
- case UINT32 : writeUInt32 (number, (Integer )value); break;
- case SFIXED32: writeSFixed32(number, (Integer )value); break;
- case SFIXED64: writeSFixed64(number, (Long )value); break;
- case SINT32 : writeSInt32 (number, (Integer )value); break;
- case SINT64 : writeSInt64 (number, (Long )value); break;
+ case DOUBLE : writeDoubleNoTag ((Double ) value); break;
+ case FLOAT : writeFloatNoTag ((Float ) value); break;
+ case INT64 : writeInt64NoTag ((Long ) value); break;
+ case UINT64 : writeUInt64NoTag ((Long ) value); break;
+ case INT32 : writeInt32NoTag ((Integer ) value); break;
+ case FIXED64 : writeFixed64NoTag ((Long ) value); break;
+ case FIXED32 : writeFixed32NoTag ((Integer ) value); break;
+ case BOOL : writeBoolNoTag ((Boolean ) value); break;
+ case STRING : writeStringNoTag ((String ) value); break;
+ case GROUP : writeGroupNoTag ((Message ) value); break;
+ case MESSAGE : writeMessageNoTag ((Message ) value); break;
+ case BYTES : writeBytesNoTag ((ByteString) value); break;
+ case UINT32 : writeUInt32NoTag ((Integer ) value); break;
+ case SFIXED32: writeSFixed32NoTag((Integer ) value); break;
+ case SFIXED64: writeSFixed64NoTag((Long ) value); break;
+ case SINT32 : writeSInt32NoTag ((Integer ) value); break;
+ case SINT64 : writeSInt64NoTag ((Long ) value); break;
case ENUM:
- writeEnum(number, ((Descriptors.EnumValueDescriptor)value).getNumber());
+ writeEnumNoTag(((Descriptors.EnumValueDescriptor) value).getNumber());
break;
}
}
+ // -----------------------------------------------------------------
+
+ /** Write a {@code double} field to the stream. */
+ public void writeDoubleNoTag(double value) throws IOException {
+ writeRawLittleEndian64(Double.doubleToRawLongBits(value));
+ }
+
+ /** Write a {@code float} field to the stream. */
+ public void writeFloatNoTag(float value) throws IOException {
+ writeRawLittleEndian32(Float.floatToRawIntBits(value));
+ }
+
+ /** Write a {@code uint64} field to the stream. */
+ public void writeUInt64NoTag(long value) throws IOException {
+ writeRawVarint64(value);
+ }
+
+ /** Write an {@code int64} field to the stream. */
+ public void writeInt64NoTag(long value) throws IOException {
+ writeRawVarint64(value);
+ }
+
+ /** Write an {@code int32} field to the stream. */
+ public void writeInt32NoTag(int value) throws IOException {
+ if (value >= 0) {
+ writeRawVarint32(value);
+ } else {
+ // Must sign-extend.
+ writeRawVarint64(value);
+ }
+ }
+
+ /** Write a {@code fixed64} field to the stream. */
+ public void writeFixed64NoTag(long value) throws IOException {
+ writeRawLittleEndian64(value);
+ }
+
+ /** Write a {@code fixed32} field to the stream. */
+ public void writeFixed32NoTag(int value) throws IOException {
+ writeRawLittleEndian32(value);
+ }
+
+ /** Write a {@code bool} field to the stream. */
+ public void writeBoolNoTag(boolean value) throws IOException {
+ writeRawByte(value ? 1 : 0);
+ }
+
+ /** Write a {@code string} field to the stream. */
+ public void writeStringNoTag(String value) throws IOException {
+ // Unfortunately there does not appear to be any way to tell Java to encode
+ // UTF-8 directly into our buffer, so we have to let it create its own byte
+ // array and then copy.
+ byte[] bytes = value.getBytes("UTF-8");
+ writeRawVarint32(bytes.length);
+ writeRawBytes(bytes);
+ }
+
+ /** Write a {@code group} field to the stream. */
+ public void writeGroupNoTag(Message value) throws IOException {
+ value.writeTo(this);
+ }
+
+ /** Write a group represented by an {@link UnknownFieldSet}. */
+ public void writeUnknownGroupNoTag(UnknownFieldSet value)
+ throws IOException {
+ value.writeTo(this);
+ }
+
+ /** Write an embedded message field to the stream. */
+ public void writeMessageNoTag(Message value) throws IOException {
+ writeRawVarint32(value.getSerializedSize());
+ value.writeTo(this);
+ }
+
+ /** Write a {@code bytes} field to the stream. */
+ public void writeBytesNoTag(ByteString value) throws IOException {
+ byte[] bytes = value.toByteArray();
+ writeRawVarint32(bytes.length);
+ writeRawBytes(bytes);
+ }
+
+ /** Write a {@code uint32} field to the stream. */
+ public void writeUInt32NoTag(int value) throws IOException {
+ writeRawVarint32(value);
+ }
+
+ /**
+ * Write an enum field to the stream. Caller is responsible
+ * for converting the enum value to its numeric value.
+ */
+ public void writeEnumNoTag(int value) throws IOException {
+ writeRawVarint32(value);
+ }
+
+ /** Write an {@code sfixed32} field to the stream. */
+ public void writeSFixed32NoTag(int value) throws IOException {
+ writeRawLittleEndian32(value);
+ }
+
+ /** Write an {@code sfixed64} field to the stream. */
+ public void writeSFixed64NoTag(long value) throws IOException {
+ writeRawLittleEndian64(value);
+ }
+
+ /** Write an {@code sint32} field to the stream. */
+ public void writeSInt32NoTag(int value) throws IOException {
+ writeRawVarint32(encodeZigZag32(value));
+ }
+
+ /** Write an {@code sint64} field to the stream. */
+ public void writeSInt64NoTag(long value) throws IOException {
+ writeRawVarint64(encodeZigZag64(value));
+ }
+
// =================================================================
/**
@@ -316,7 +439,7 @@ public final class CodedOutputStream {
* {@code double} field, including tag.
*/
public static int computeDoubleSize(int fieldNumber, double value) {
- return computeTagSize(fieldNumber) + LITTLE_ENDIAN_64_SIZE;
+ return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value);
}
/**
@@ -324,7 +447,7 @@ public final class CodedOutputStream {
* {@code float} field, including tag.
*/
public static int computeFloatSize(int fieldNumber, float value) {
- return computeTagSize(fieldNumber) + LITTLE_ENDIAN_32_SIZE;
+ return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value);
}
/**
@@ -332,7 +455,7 @@ public final class CodedOutputStream {
* {@code uint64} field, including tag.
*/
public static int computeUInt64Size(int fieldNumber, long value) {
- return computeTagSize(fieldNumber) + computeRawVarint64Size(value);
+ return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value);
}
/**
@@ -340,7 +463,7 @@ public final class CodedOutputStream {
* {@code int64} field, including tag.
*/
public static int computeInt64Size(int fieldNumber, long value) {
- return computeTagSize(fieldNumber) + computeRawVarint64Size(value);
+ return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value);
}
/**
@@ -348,12 +471,7 @@ public final class CodedOutputStream {
* {@code int32} field, including tag.
*/
public static int computeInt32Size(int fieldNumber, int value) {
- if (value >= 0) {
- return computeTagSize(fieldNumber) + computeRawVarint32Size(value);
- } else {
- // Must sign-extend.
- return computeTagSize(fieldNumber) + 10;
- }
+ return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value);
}
/**
@@ -361,7 +479,7 @@ public final class CodedOutputStream {
* {@code fixed64} field, including tag.
*/
public static int computeFixed64Size(int fieldNumber, long value) {
- return computeTagSize(fieldNumber) + LITTLE_ENDIAN_64_SIZE;
+ return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value);
}
/**
@@ -369,7 +487,7 @@ public final class CodedOutputStream {
* {@code fixed32} field, including tag.
*/
public static int computeFixed32Size(int fieldNumber, int value) {
- return computeTagSize(fieldNumber) + LITTLE_ENDIAN_32_SIZE;
+ return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value);
}
/**
@@ -377,7 +495,7 @@ public final class CodedOutputStream {
* {@code bool} field, including tag.
*/
public static int computeBoolSize(int fieldNumber, boolean value) {
- return computeTagSize(fieldNumber) + 1;
+ return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value);
}
/**
@@ -385,14 +503,7 @@ public final class CodedOutputStream {
* {@code string} field, including tag.
*/
public static int computeStringSize(int fieldNumber, String value) {
- try {
- byte[] bytes = value.getBytes("UTF-8");
- return computeTagSize(fieldNumber) +
- computeRawVarint32Size(bytes.length) +
- bytes.length;
- } catch (java.io.UnsupportedEncodingException e) {
- throw new RuntimeException("UTF-8 not supported.", e);
- }
+ return computeTagSize(fieldNumber) + computeStringSizeNoTag(value);
}
/**
@@ -400,7 +511,7 @@ public final class CodedOutputStream {
* {@code group} field, including tag.
*/
public static int computeGroupSize(int fieldNumber, Message value) {
- return computeTagSize(fieldNumber) * 2 + value.getSerializedSize();
+ return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value);
}
/**
@@ -410,7 +521,8 @@ public final class CodedOutputStream {
*/
public static int computeUnknownGroupSize(int fieldNumber,
UnknownFieldSet value) {
- return computeTagSize(fieldNumber) * 2 + value.getSerializedSize();
+ return computeTagSize(fieldNumber) * 2 +
+ computeUnknownGroupSizeNoTag(value);
}
/**
@@ -418,8 +530,7 @@ public final class CodedOutputStream {
* embedded message field, including tag.
*/
public static int computeMessageSize(int fieldNumber, Message value) {
- int size = value.getSerializedSize();
- return computeTagSize(fieldNumber) + computeRawVarint32Size(size) + size;
+ return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value);
}
/**
@@ -427,9 +538,7 @@ public final class CodedOutputStream {
* {@code bytes} field, including tag.
*/
public static int computeBytesSize(int fieldNumber, ByteString value) {
- return computeTagSize(fieldNumber) +
- computeRawVarint32Size(value.size()) +
- value.size();
+ return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value);
}
/**
@@ -437,7 +546,7 @@ public final class CodedOutputStream {
* {@code uint32} field, including tag.
*/
public static int computeUInt32Size(int fieldNumber, int value) {
- return computeTagSize(fieldNumber) + computeRawVarint32Size(value);
+ return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value);
}
/**
@@ -446,7 +555,7 @@ public final class CodedOutputStream {
* enum value to its numeric value.
*/
public static int computeEnumSize(int fieldNumber, int value) {
- return computeTagSize(fieldNumber) + computeRawVarint32Size(value);
+ return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value);
}
/**
@@ -454,7 +563,7 @@ public final class CodedOutputStream {
* {@code sfixed32} field, including tag.
*/
public static int computeSFixed32Size(int fieldNumber, int value) {
- return computeTagSize(fieldNumber) + LITTLE_ENDIAN_32_SIZE;
+ return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value);
}
/**
@@ -462,7 +571,7 @@ public final class CodedOutputStream {
* {@code sfixed64} field, including tag.
*/
public static int computeSFixed64Size(int fieldNumber, long value) {
- return computeTagSize(fieldNumber) + LITTLE_ENDIAN_64_SIZE;
+ return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value);
}
/**
@@ -470,8 +579,7 @@ public final class CodedOutputStream {
* {@code sint32} field, including tag.
*/
public static int computeSInt32Size(int fieldNumber, int value) {
- return computeTagSize(fieldNumber) +
- computeRawVarint32Size(encodeZigZag32(value));
+ return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value);
}
/**
@@ -479,8 +587,7 @@ public final class CodedOutputStream {
* {@code sint64} field, including tag.
*/
public static int computeSInt64Size(int fieldNumber, long value) {
- return computeTagSize(fieldNumber) +
- computeRawVarint64Size(encodeZigZag64(value));
+ return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value);
}
/**
@@ -507,6 +614,174 @@ public final class CodedOutputStream {
computeBytesSize(WireFormat.MESSAGE_SET_MESSAGE, value);
}
+ // -----------------------------------------------------------------
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code double} field, including tag.
+ */
+ public static int computeDoubleSizeNoTag(double value) {
+ return LITTLE_ENDIAN_64_SIZE;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code float} field, including tag.
+ */
+ public static int computeFloatSizeNoTag(float value) {
+ return LITTLE_ENDIAN_32_SIZE;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code uint64} field, including tag.
+ */
+ public static int computeUInt64SizeNoTag(long value) {
+ return computeRawVarint64Size(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code int64} field, including tag.
+ */
+ public static int computeInt64SizeNoTag(long value) {
+ return computeRawVarint64Size(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code int32} field, including tag.
+ */
+ public static int computeInt32SizeNoTag(int value) {
+ if (value >= 0) {
+ return computeRawVarint32Size(value);
+ } else {
+ // Must sign-extend.
+ return 10;
+ }
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code fixed64} field.
+ */
+ public static int computeFixed64SizeNoTag(long value) {
+ return LITTLE_ENDIAN_64_SIZE;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code fixed32} field.
+ */
+ public static int computeFixed32SizeNoTag(int value) {
+ return LITTLE_ENDIAN_32_SIZE;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code bool} field.
+ */
+ public static int computeBoolSizeNoTag(boolean value) {
+ return 1;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code string} field.
+ */
+ public static int computeStringSizeNoTag(String value) {
+ try {
+ byte[] bytes = value.getBytes("UTF-8");
+ return computeRawVarint32Size(bytes.length) +
+ bytes.length;
+ } catch (java.io.UnsupportedEncodingException e) {
+ throw new RuntimeException("UTF-8 not supported.", e);
+ }
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code group} field.
+ */
+ public static int computeGroupSizeNoTag(Message value) {
+ return value.getSerializedSize();
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code group} field represented by an {@code UnknownFieldSet}, including
+ * tag.
+ */
+ public static int computeUnknownGroupSizeNoTag(UnknownFieldSet value) {
+ return value.getSerializedSize();
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an embedded
+ * message field.
+ */
+ public static int computeMessageSizeNoTag(Message value) {
+ int size = value.getSerializedSize();
+ return computeRawVarint32Size(size) + size;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code bytes} field.
+ */
+ public static int computeBytesSizeNoTag(ByteString value) {
+ return computeRawVarint32Size(value.size()) +
+ value.size();
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code uint32} field.
+ */
+ public static int computeUInt32SizeNoTag(int value) {
+ return computeRawVarint32Size(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an enum field.
+ * Caller is responsible for converting the enum value to its numeric value.
+ */
+ public static int computeEnumSizeNoTag(int value) {
+ return computeRawVarint32Size(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code sfixed32} field.
+ */
+ public static int computeSFixed32SizeNoTag(int value) {
+ return LITTLE_ENDIAN_32_SIZE;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code sfixed64} field.
+ */
+ public static int computeSFixed64SizeNoTag(long value) {
+ return LITTLE_ENDIAN_64_SIZE;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code sint32} field.
+ */
+ public static int computeSInt32SizeNoTag(int value) {
+ return computeRawVarint32Size(encodeZigZag32(value));
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code sint64} field.
+ */
+ public static int computeSInt64SizeNoTag(long value) {
+ return computeRawVarint64Size(encodeZigZag64(value));
+ }
+
/**
* Compute the number of bytes that would be needed to encode a
* field of arbitrary type, including tag, to the stream.
@@ -521,28 +796,48 @@ public final class CodedOutputStream {
public static int computeFieldSize(
Descriptors.FieldDescriptor.Type type,
int number, Object value) {
+ int tagSize = computeTagSize(number);
+ if (type == Descriptors.FieldDescriptor.Type.GROUP) {
+ tagSize *= 2;
+ }
+ return tagSize + computeFieldSizeNoTag(type, value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * field of arbitrary type, excluding tag, to the stream.
+ *
+ * @param type The field's type.
+ * @param number The field's number.
+ * @param value Object representing the field's value. Must be of the exact
+ * type which would be returned by
+ * {@link Message#getField(Descriptors.FieldDescriptor)} for
+ * this field.
+ */
+ public static int computeFieldSizeNoTag(
+ Descriptors.FieldDescriptor.Type type, Object value) {
switch (type) {
- case DOUBLE : return computeDoubleSize (number, (Double )value);
- case FLOAT : return computeFloatSize (number, (Float )value);
- case INT64 : return computeInt64Size (number, (Long )value);
- case UINT64 : return computeUInt64Size (number, (Long )value);
- case INT32 : return computeInt32Size (number, (Integer )value);
- case FIXED64 : return computeFixed64Size (number, (Long )value);
- case FIXED32 : return computeFixed32Size (number, (Integer )value);
- case BOOL : return computeBoolSize (number, (Boolean )value);
- case STRING : return computeStringSize (number, (String )value);
- case GROUP : return computeGroupSize (number, (Message )value);
- case MESSAGE : return computeMessageSize (number, (Message )value);
- case BYTES : return computeBytesSize (number, (ByteString)value);
- case UINT32 : return computeUInt32Size (number, (Integer )value);
- case SFIXED32: return computeSFixed32Size(number, (Integer )value);
- case SFIXED64: return computeSFixed64Size(number, (Long )value);
- case SINT32 : return computeSInt32Size (number, (Integer )value);
- case SINT64 : return computeSInt64Size (number, (Long )value);
+ case DOUBLE : return computeDoubleSizeNoTag ((Double )value);
+ case FLOAT : return computeFloatSizeNoTag ((Float )value);
+ case INT64 : return computeInt64SizeNoTag ((Long )value);
+ case UINT64 : return computeUInt64SizeNoTag ((Long )value);
+ case INT32 : return computeInt32SizeNoTag ((Integer )value);
+ case FIXED64 : return computeFixed64SizeNoTag ((Long )value);
+ case FIXED32 : return computeFixed32SizeNoTag ((Integer )value);
+ case BOOL : return computeBoolSizeNoTag ((Boolean )value);
+ case STRING : return computeStringSizeNoTag ((String )value);
+ case GROUP : return computeGroupSizeNoTag ((Message )value);
+ case MESSAGE : return computeMessageSizeNoTag ((Message )value);
+ case BYTES : return computeBytesSizeNoTag ((ByteString)value);
+ case UINT32 : return computeUInt32SizeNoTag ((Integer )value);
+ case SFIXED32: return computeSFixed32SizeNoTag((Integer )value);
+ case SFIXED64: return computeSFixed64SizeNoTag((Long )value);
+ case SINT32 : return computeSInt32SizeNoTag ((Integer )value);
+ case SINT64 : return computeSInt64SizeNoTag ((Long )value);
case ENUM:
- return computeEnumSize(number,
- ((Descriptors.EnumValueDescriptor)value).getNumber());
+ return computeEnumSizeNoTag(
+ ((Descriptors.EnumValueDescriptor)value).getNumber());
}
throw new RuntimeException(
diff --git a/java/src/main/java/com/google/protobuf/Descriptors.java b/java/src/main/java/com/google/protobuf/Descriptors.java
index ee4d4e3a..80266a59 100644
--- a/java/src/main/java/com/google/protobuf/Descriptors.java
+++ b/java/src/main/java/com/google/protobuf/Descriptors.java
@@ -857,6 +857,19 @@ public final class Descriptors {
"Field numbers must be positive integers.");
}
+ // Only repeated primitive fields may be packed.
+ if (proto.getOptions().getPacked()) {
+ if (proto.getLabel() != FieldDescriptorProto.Label.LABEL_REPEATED ||
+ proto.getType() == FieldDescriptorProto.Type.TYPE_STRING ||
+ proto.getType() == FieldDescriptorProto.Type.TYPE_GROUP ||
+ proto.getType() == FieldDescriptorProto.Type.TYPE_MESSAGE ||
+ proto.getType() == FieldDescriptorProto.Type.TYPE_BYTES) {
+ throw new DescriptorValidationException(this,
+ "[packed = true] can only be specified for repeated primitive " +
+ "fields.");
+ }
+ }
+
if (isExtension) {
if (!proto.hasExtendee()) {
throw new DescriptorValidationException(this,
diff --git a/java/src/main/java/com/google/protobuf/DynamicMessage.java b/java/src/main/java/com/google/protobuf/DynamicMessage.java
index fefa23ec..99ae253c 100644
--- a/java/src/main/java/com/google/protobuf/DynamicMessage.java
+++ b/java/src/main/java/com/google/protobuf/DynamicMessage.java
@@ -211,6 +211,10 @@ public final class DynamicMessage extends AbstractMessage {
return new Builder(type);
}
+ public Builder toBuilder() {
+ return newBuilderForType().mergeFrom(this);
+ }
+
/** Verifies that the field is a field of this message. */
private void verifyContainingType(FieldDescriptor field) {
if (field.getContainingType() != type) {
@@ -251,6 +255,7 @@ public final class DynamicMessage extends AbstractMessage {
}
fields.mergeFrom(other);
+ mergeUnknownFields(other.getUnknownFields());
return this;
}
diff --git a/java/src/main/java/com/google/protobuf/FieldSet.java b/java/src/main/java/com/google/protobuf/FieldSet.java
index 98a1c328..01da3faf 100644
--- a/java/src/main/java/com/google/protobuf/FieldSet.java
+++ b/java/src/main/java/com/google/protobuf/FieldSet.java
@@ -351,8 +351,7 @@ final class FieldSet {
setField(field, entry.getValue());
} else {
setField(field,
- existingValue.newBuilderForType()
- .mergeFrom(existingValue)
+ existingValue.toBuilder()
.mergeFrom((Message)entry.getValue())
.build());
}
@@ -384,8 +383,7 @@ final class FieldSet {
setField(field, value);
} else {
setField(field,
- existingValue.newBuilderForType()
- .mergeFrom(existingValue)
+ existingValue.toBuilder()
.mergeFrom((Message)value)
.build());
}
@@ -463,60 +461,83 @@ final class FieldSet {
}
if (field == null ||
- wireType != WireFormat.getWireFormatForFieldType(field.getType())) {
+ wireType != WireFormat.getWireFormatForField(field)) {
// Unknown field or wrong wire type. Skip.
return unknownFields.mergeFieldFrom(tag, input);
} else {
- Object value;
- switch (field.getType()) {
- case GROUP: {
- Message.Builder subBuilder;
- if (defaultInstance != null) {
- subBuilder = defaultInstance.newBuilderForType();
- } else {
- subBuilder = builder.newBuilderForField(field);
+ if (field.getOptions().getPacked()) {
+ int length = input.readRawVarint32();
+ int limit = input.pushLimit(length);
+ if (field.getType() == FieldDescriptor.Type.ENUM) {
+ while (input.getBytesUntilLimit() > 0) {
+ int rawValue = input.readEnum();
+ Object value = field.getEnumType().findValueByNumber(rawValue);
+ if (value == null) {
+ // If the number isn't recognized as a valid value for this
+ // enum, drop it (don't even add it to unknownFields).
+ return true;
+ }
+ builder.addRepeatedField(field, value);
}
- if (!field.isRepeated()) {
- subBuilder.mergeFrom((Message) builder.getField(field));
+ } else {
+ while (input.getBytesUntilLimit() > 0) {
+ Object value = input.readPrimitiveField(field.getType());
+ builder.addRepeatedField(field, value);
}
- input.readGroup(field.getNumber(), subBuilder, extensionRegistry);
- value = subBuilder.build();
- break;
}
- case MESSAGE: {
- Message.Builder subBuilder;
- if (defaultInstance != null) {
- subBuilder = defaultInstance.newBuilderForType();
- } else {
- subBuilder = builder.newBuilderForField(field);
+ input.popLimit(limit);
+ } else {
+ Object value;
+ switch (field.getType()) {
+ case GROUP: {
+ Message.Builder subBuilder;
+ if (defaultInstance != null) {
+ subBuilder = defaultInstance.newBuilderForType();
+ } else {
+ subBuilder = builder.newBuilderForField(field);
+ }
+ if (!field.isRepeated()) {
+ subBuilder.mergeFrom((Message) builder.getField(field));
+ }
+ input.readGroup(field.getNumber(), subBuilder, extensionRegistry);
+ value = subBuilder.build();
+ break;
}
- if (!field.isRepeated()) {
- subBuilder.mergeFrom((Message) builder.getField(field));
+ case MESSAGE: {
+ Message.Builder subBuilder;
+ if (defaultInstance != null) {
+ subBuilder = defaultInstance.newBuilderForType();
+ } else {
+ subBuilder = builder.newBuilderForField(field);
+ }
+ if (!field.isRepeated()) {
+ subBuilder.mergeFrom((Message) builder.getField(field));
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ value = subBuilder.build();
+ break;
}
- input.readMessage(subBuilder, extensionRegistry);
- value = subBuilder.build();
- break;
- }
- case ENUM: {
- int rawValue = input.readEnum();
- value = field.getEnumType().findValueByNumber(rawValue);
- // If the number isn't recognized as a valid value for this enum,
- // drop it.
- if (value == null) {
- unknownFields.mergeVarintField(fieldNumber, rawValue);
- return true;
+ case ENUM: {
+ int rawValue = input.readEnum();
+ value = field.getEnumType().findValueByNumber(rawValue);
+ // If the number isn't recognized as a valid value for this enum,
+ // drop it.
+ if (value == null) {
+ unknownFields.mergeVarintField(fieldNumber, rawValue);
+ return true;
+ }
+ break;
}
- break;
+ default:
+ value = input.readPrimitiveField(field.getType());
+ break;
}
- default:
- value = input.readPrimitiveField(field.getType());
- break;
- }
- if (field.isRepeated()) {
- builder.addRepeatedField(field, value);
- } else {
- builder.setField(field, value);
+ if (field.isRepeated()) {
+ builder.addRepeatedField(field, value);
+ } else {
+ builder.setField(field, value);
+ }
}
}
@@ -636,8 +657,24 @@ final class FieldSet {
output.writeMessageSetExtension(field.getNumber(), (Message)value);
} else {
if (field.isRepeated()) {
- for (Object element : (List)value) {
- output.writeField(field.getType(), field.getNumber(), element);
+ List valueList = (List)value;
+ if (field.getOptions().getPacked()) {
+ output.writeTag(field.getNumber(),
+ WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ // Compute the total data size so the length can be written.
+ int dataSize = 0;
+ for (Object element : valueList) {
+ dataSize += output.computeFieldSizeNoTag(field.getType(), element);
+ }
+ output.writeRawVarint32(dataSize);
+ // Write the data itself, without any tags.
+ for (Object element : valueList) {
+ output.writeFieldNoTag(field.getType(), element);
+ }
+ } else {
+ for (Object element : valueList) {
+ output.writeField(field.getType(), field.getNumber(), element);
+ }
}
} else {
output.writeField(field.getType(), field.getNumber(), value);
@@ -658,12 +695,23 @@ final class FieldSet {
if (field.isExtension() &&
field.getContainingType().getOptions().getMessageSetWireFormat()) {
size += CodedOutputStream.computeMessageSetExtensionSize(
- field.getNumber(), (Message)value);
+ field.getNumber(), (Message) value);
} else {
if (field.isRepeated()) {
- for (Object element : (List)value) {
- size += CodedOutputStream.computeFieldSize(
- field.getType(), field.getNumber(), element);
+ if (field.getOptions().getPacked()) {
+ int dataSize = 0;
+ for (Object element : (List)value) {
+ dataSize += CodedOutputStream.computeFieldSizeNoTag(
+ field.getType(), element);
+ }
+ size += dataSize +
+ CodedOutputStream.computeTagSize(field.getNumber()) +
+ CodedOutputStream.computeRawVarint32Size(dataSize);
+ } else {
+ for (Object element : (List)value) {
+ size += CodedOutputStream.computeFieldSize(
+ field.getType(), field.getNumber(), element);
+ }
}
} else {
size += CodedOutputStream.computeFieldSize(
diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessage.java b/java/src/main/java/com/google/protobuf/GeneratedMessage.java
index b1be8b14..77c88c30 100644
--- a/java/src/main/java/com/google/protobuf/GeneratedMessage.java
+++ b/java/src/main/java/com/google/protobuf/GeneratedMessage.java
@@ -31,8 +31,8 @@
package com.google.protobuf;
import com.google.protobuf.Descriptors.Descriptor;
-import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
import java.io.IOException;
import java.lang.reflect.Method;
@@ -75,7 +75,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
for (FieldDescriptor field : descriptor.getFields()) {
if (field.isRepeated()) {
- List value = (List)getField(field);
+ List value = (List) getField(field);
if (!value.isEmpty()) {
result.put(field, value);
}
@@ -87,7 +87,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
}
return result;
}
-
+
public boolean isInitialized() {
for (FieldDescriptor field : getDescriptorForType().getFields()) {
// Check that all required fields are present.
@@ -99,7 +99,9 @@ public abstract class GeneratedMessage extends AbstractMessage {
// Check that embedded messages are initialized.
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
if (field.isRepeated()) {
- for (Message element : (List<Message>) getField(field)) {
+ @SuppressWarnings("unchecked")
+ List<Message> messageList = (List<Message>) getField(field);
+ for (Message element : messageList) {
if (!element.isInitialized()) {
return false;
}
@@ -189,7 +191,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
setField(field, entry.getValue());
}
}
- return (BuilderType)this;
+ return (BuilderType) this;
}
public Descriptor getDescriptorForType() {
@@ -214,7 +216,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
// The underlying list object is still modifiable at this point.
// Make sure not to expose the modifiable list to the caller.
return Collections.unmodifiableList(
- (List)internalGetResult().getField(field));
+ (List) internalGetResult().getField(field));
} else {
return internalGetResult().getField(field);
}
@@ -223,12 +225,12 @@ public abstract class GeneratedMessage extends AbstractMessage {
public BuilderType setField(Descriptors.FieldDescriptor field,
Object value) {
internalGetFieldAccessorTable().getField(field).set(this, value);
- return (BuilderType)this;
+ return (BuilderType) this;
}
public BuilderType clearField(Descriptors.FieldDescriptor field) {
internalGetFieldAccessorTable().getField(field).clear(this);
- return (BuilderType)this;
+ return (BuilderType) this;
}
public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) {
@@ -244,13 +246,13 @@ public abstract class GeneratedMessage extends AbstractMessage {
int index, Object value) {
internalGetFieldAccessorTable().getField(field)
.setRepeated(this, index, value);
- return (BuilderType)this;
+ return (BuilderType) this;
}
public BuilderType addRepeatedField(Descriptors.FieldDescriptor field,
Object value) {
internalGetFieldAccessorTable().getField(field).addRepeated(this, value);
- return (BuilderType)this;
+ return (BuilderType) this;
}
public final UnknownFieldSet getUnknownFields() {
@@ -259,7 +261,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
public final BuilderType setUnknownFields(UnknownFieldSet unknownFields) {
internalGetResult().unknownFields = unknownFields;
- return (BuilderType)this;
+ return (BuilderType) this;
}
public final BuilderType mergeUnknownFields(UnknownFieldSet unknownFields) {
@@ -268,7 +270,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
UnknownFieldSet.newBuilder(result.unknownFields)
.mergeFrom(unknownFields)
.build();
- return (BuilderType)this;
+ return (BuilderType) this;
}
public boolean isInitialized() {
@@ -287,7 +289,18 @@ public abstract class GeneratedMessage extends AbstractMessage {
return unknownFields.mergeFieldFrom(tag, input);
}
+ /**
+ * Adds the {@code values} to the {@code list}.
+ *
+ * @throws NullPointerException if any of the elements of {@code values} is
+ * null.
+ */
protected <T> void addAll(Iterable<T> values, Collection<? super T> list) {
+ for (T value : values) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ }
if (values instanceof Collection) {
@SuppressWarnings("unsafe")
Collection<T> collection = (Collection<T>) values;
@@ -378,9 +391,9 @@ public abstract class GeneratedMessage extends AbstractMessage {
verifyExtensionContainingType(extension);
Object value = extensions.getField(extension.getDescriptor());
if (value == null) {
- return (Type)extension.getMessageDefaultInstance();
+ return (Type) extension.getMessageDefaultInstance();
} else {
- return (Type)extension.fromReflectionType(value);
+ return (Type) extension.fromReflectionType(value);
}
}
@@ -389,7 +402,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
public final <Type> Type getExtension(
GeneratedExtension<MessageType, List<Type>> extension, int index) {
verifyExtensionContainingType(extension);
- return (Type)extension.singularFromReflectionType(
+ return (Type) extension.singularFromReflectionType(
extensions.getRepeatedField(extension.getDescriptor(), index));
}
@@ -397,7 +410,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
protected boolean extensionsAreInitialized() {
return extensions.isInitialized();
}
-
+
public boolean isInitialized() {
return super.isInitialized() && extensionsAreInitialized();
}
@@ -580,7 +593,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
message.verifyExtensionContainingType(extension);
message.extensions.setField(extension.getDescriptor(),
extension.toReflectionType(value));
- return (BuilderType)this;
+ return (BuilderType) this;
}
/** Set the value of one element of a repeated extension. */
@@ -592,7 +605,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
message.extensions.setRepeatedField(
extension.getDescriptor(), index,
extension.singularToReflectionType(value));
- return (BuilderType)this;
+ return (BuilderType) this;
}
/** Append a value to a repeated extension. */
@@ -602,7 +615,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
message.verifyExtensionContainingType(extension);
message.extensions.addRepeatedField(
extension.getDescriptor(), extension.singularToReflectionType(value));
- return (BuilderType)this;
+ return (BuilderType) this;
}
/** Clear an extension. */
@@ -611,7 +624,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
ExtendableMessage<MessageType> message = internalGetResult();
message.verifyExtensionContainingType(extension);
message.extensions.clearField(extension.getDescriptor());
- return (BuilderType)this;
+ return (BuilderType) this;
}
/**
@@ -639,7 +652,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
ExtendableMessage<MessageType> message = internalGetResult();
message.verifyContainingType(field);
message.extensions.setField(field, value);
- return (BuilderType)this;
+ return (BuilderType) this;
} else {
return super.setField(field, value);
}
@@ -650,7 +663,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
ExtendableMessage<MessageType> message = internalGetResult();
message.verifyContainingType(field);
message.extensions.clearField(field);
- return (BuilderType)this;
+ return (BuilderType) this;
} else {
return super.clearField(field);
}
@@ -662,7 +675,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
ExtendableMessage<MessageType> message = internalGetResult();
message.verifyContainingType(field);
message.extensions.setRepeatedField(field, index, value);
- return (BuilderType)this;
+ return (BuilderType) this;
} else {
return super.setRepeatedField(field, index, value);
}
@@ -674,11 +687,15 @@ public abstract class GeneratedMessage extends AbstractMessage {
ExtendableMessage<MessageType> message = internalGetResult();
message.verifyContainingType(field);
message.extensions.addRepeatedField(field, value);
- return (BuilderType)this;
+ return (BuilderType) this;
} else {
return super.addRepeatedField(field, value);
}
}
+
+ protected final void mergeExtensionFields(ExtendableMessage other) {
+ internalGetResult().extensions.mergeFrom(other.extensions);
+ }
}
// -----------------------------------------------------------------
@@ -750,8 +767,8 @@ public abstract class GeneratedMessage extends AbstractMessage {
enumValueOf = null;
enumGetValueDescriptor = null;
messageDefaultInstance =
- (Message)invokeOrDie(getMethodOrDie(type, "getDefaultInstance"),
- null);
+ (Message) invokeOrDie(getMethodOrDie(type, "getDefaultInstance"),
+ null);
break;
case ENUM:
enumValueOf = getMethodOrDie(type, "valueOf",
@@ -797,7 +814,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) {
// Must convert the whole list.
List result = new ArrayList();
- for (Object element : (List)value) {
+ for (Object element : (List) value) {
result.add(singularFromReflectionType(element));
}
return result;
@@ -826,10 +843,10 @@ public abstract class GeneratedMessage extends AbstractMessage {
// This should not happen in normal use. But, to be nice, we'll
// copy the message to whatever type the caller was expecting.
return messageDefaultInstance.newBuilderForType()
- .mergeFrom((Message)value).build();
+ .mergeFrom((Message) value).build();
}
case ENUM:
- return invokeOrDie(enumValueOf, null, (EnumValueDescriptor)value);
+ return invokeOrDie(enumValueOf, null, (EnumValueDescriptor) value);
default:
return value;
}
@@ -847,7 +864,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
if (descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) {
// Must convert the whole list.
List result = new ArrayList();
- for (Object element : (List)value) {
+ for (Object element : (List) value) {
result.add(singularToReflectionType(element));
}
return result;
@@ -900,9 +917,9 @@ public abstract class GeneratedMessage extends AbstractMessage {
} catch (java.lang.reflect.InvocationTargetException e) {
Throwable cause = e.getCause();
if (cause instanceof RuntimeException) {
- throw (RuntimeException)cause;
+ throw (RuntimeException) cause;
} else if (cause instanceof Error) {
- throw (Error)cause;
+ throw (Error) cause;
} else {
throw new RuntimeException(
"Unexpected exception thrown by generated accessor method.", cause);
@@ -915,6 +932,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
* with access to the fields of a message object using Java reflection.
*/
public static final class FieldAccessorTable {
+
/**
* Construct a FieldAccessorTable for a particular message class. Only
* one FieldAccessorTable should ever be constructed per class.
@@ -1039,7 +1057,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
"addRepeatedField() called on a singular field.");
}
public boolean has(GeneratedMessage message) {
- return (Boolean)invokeOrDie(hasMethod, message);
+ return (Boolean) invokeOrDie(hasMethod, message);
}
public int getRepeatedCount(GeneratedMessage message) {
throw new UnsupportedOperationException(
@@ -1092,7 +1110,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
// 2) Insures that the caller cannot modify the list later on and
// have the modifications be reflected in the message.
clear(builder);
- for (Object element : (List)value) {
+ for (Object element : (List) value) {
addRepeated(builder, element);
}
}
@@ -1111,7 +1129,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
"hasField() called on a singular field.");
}
public int getRepeatedCount(GeneratedMessage message) {
- return (Integer)invokeOrDie(getCountMethod, message);
+ return (Integer) invokeOrDie(getCountMethod, message);
}
public void clear(GeneratedMessage.Builder builder) {
invokeOrDie(clearMethod, builder);
@@ -1169,7 +1187,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
@SuppressWarnings("unchecked")
public Object get(GeneratedMessage message) {
List newList = new ArrayList();
- for (Object element : (List)super.get(message)) {
+ for (Object element : (List) super.get(message)) {
newList.add(invokeOrDie(getValueDescriptorMethod, element));
}
return Collections.unmodifiableList(newList);
@@ -1210,8 +1228,8 @@ public abstract class GeneratedMessage extends AbstractMessage {
// is an alternative implementation of the same type -- e.g. a
// DynamicMessage -- we should accept it. In this case we can make
// a copy of the message.
- return ((Message.Builder)invokeOrDie(newBuilderMethod, null))
- .mergeFrom((Message)value).build();
+ return ((Message.Builder) invokeOrDie(newBuilderMethod, null))
+ .mergeFrom((Message) value).build();
}
}
@@ -1219,7 +1237,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
super.set(builder, coerceType(value));
}
public Message.Builder newBuilder() {
- return (Message.Builder)invokeOrDie(newBuilderMethod, null);
+ return (Message.Builder) invokeOrDie(newBuilderMethod, null);
}
}
@@ -1244,8 +1262,8 @@ public abstract class GeneratedMessage extends AbstractMessage {
// is an alternative implementation of the same type -- e.g. a
// DynamicMessage -- we should accept it. In this case we can make
// a copy of the message.
- return ((Message.Builder)invokeOrDie(newBuilderMethod, null))
- .mergeFrom((Message)value).build();
+ return ((Message.Builder) invokeOrDie(newBuilderMethod, null))
+ .mergeFrom((Message) value).build();
}
}
@@ -1257,7 +1275,7 @@ public abstract class GeneratedMessage extends AbstractMessage {
super.addRepeated(builder, coerceType(value));
}
public Message.Builder newBuilder() {
- return (Message.Builder)invokeOrDie(newBuilderMethod, null);
+ return (Message.Builder) invokeOrDie(newBuilderMethod, null);
}
}
}
diff --git a/java/src/main/java/com/google/protobuf/Message.java b/java/src/main/java/com/google/protobuf/Message.java
index 9635387a..2f8700db 100644
--- a/java/src/main/java/com/google/protobuf/Message.java
+++ b/java/src/main/java/com/google/protobuf/Message.java
@@ -195,6 +195,12 @@ public interface Message {
Builder newBuilderForType();
/**
+ * Constructs a builder initialized with the current message. Use this to
+ * derive a new message from the current one.
+ */
+ Builder toBuilder();
+
+ /**
* Abstract interface implemented by Protocol Message builders.
*/
public static interface Builder extends Cloneable {
diff --git a/java/src/main/java/com/google/protobuf/TextFormat.java b/java/src/main/java/com/google/protobuf/TextFormat.java
index 3a1b1d4e..3dcf68c8 100644
--- a/java/src/main/java/com/google/protobuf/TextFormat.java
+++ b/java/src/main/java/com/google/protobuf/TextFormat.java
@@ -397,13 +397,15 @@ public final class TextFormat {
private int previousLine = 0;
private int previousColumn = 0;
+ // We use possesive quantifiers (*+ and ++) because otherwise the Java
+ // regex matcher has stack overflows on large inputs.
private static Pattern WHITESPACE =
- Pattern.compile("(\\s|(#.*$))+", Pattern.MULTILINE);
+ Pattern.compile("(\\s|(#.*$))++", Pattern.MULTILINE);
private static Pattern TOKEN = Pattern.compile(
- "[a-zA-Z_][0-9a-zA-Z_+-]*|" + // an identifier
- "[0-9+-][0-9a-zA-Z_.+-]*|" + // a number
- "\"([^\"\n\\\\]|\\\\.)*(\"|\\\\?$)|" + // a double-quoted string
- "\'([^\"\n\\\\]|\\\\.)*(\'|\\\\?$)", // a single-quoted string
+ "[a-zA-Z_][0-9a-zA-Z_+-]*+|" + // an identifier
+ "[0-9+-][0-9a-zA-Z_.+-]*+|" + // a number
+ "\"([^\"\n\\\\]|\\\\.)*+(\"|\\\\?$)|" + // a double-quoted string
+ "\'([^\"\n\\\\]|\\\\.)*+(\'|\\\\?$)", // a single-quoted string
Pattern.MULTILINE);
private static Pattern DOUBLE_INFINITY = Pattern.compile(
diff --git a/java/src/main/java/com/google/protobuf/WireFormat.java b/java/src/main/java/com/google/protobuf/WireFormat.java
index ff042c05..2faf2448 100644
--- a/java/src/main/java/com/google/protobuf/WireFormat.java
+++ b/java/src/main/java/com/google/protobuf/WireFormat.java
@@ -96,6 +96,16 @@ public final class WireFormat {
"There is no way to get here, but the compiler thinks otherwise.");
}
+ /** Given a field descriptor, returns the wire type. This differs from
+ * getWireFormatForFieldType for packed repeated fields. */
+ static int getWireFormatForField(Descriptors.FieldDescriptor descriptor) {
+ if (descriptor.getOptions().getPacked()) {
+ return WIRETYPE_LENGTH_DELIMITED;
+ } else {
+ return getWireFormatForFieldType(descriptor.getType());
+ }
+ }
+
// Field numbers for feilds in MessageSet wire format.
static final int MESSAGE_SET_ITEM = 1;
static final int MESSAGE_SET_TYPE_ID = 2;
diff --git a/java/src/test/java/com/google/protobuf/AbstractMessageTest.java b/java/src/test/java/com/google/protobuf/AbstractMessageTest.java
index 10ab7e75..da073561 100644
--- a/java/src/test/java/com/google/protobuf/AbstractMessageTest.java
+++ b/java/src/test/java/com/google/protobuf/AbstractMessageTest.java
@@ -34,6 +34,7 @@ import protobuf_unittest.UnittestProto;
import protobuf_unittest.UnittestProto.ForeignMessage;
import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
import protobuf_unittest.UnittestProto.TestRequired;
import protobuf_unittest.UnittestProto.TestRequiredForeign;
import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
@@ -91,6 +92,9 @@ public class AbstractMessageTest extends TestCase {
public Builder newBuilderForType() {
return new Builder(wrappedMessage.newBuilderForType());
}
+ public Builder toBuilder() {
+ return new Builder(wrappedMessage.toBuilder());
+ }
static class Builder extends AbstractMessage.Builder<Builder> {
private final Message.Builder wrappedBuilder;
@@ -215,6 +219,25 @@ public class AbstractMessageTest extends TestCase {
TestUtil.assertAllFieldsSet((TestAllTypes) message.wrappedMessage);
}
+ public void testPackedSerialization() throws Exception {
+ Message abstractMessage =
+ new AbstractMessageWrapper(TestUtil.getPackedSet());
+
+ TestUtil.assertPackedFieldsSet(
+ TestPackedTypes.parseFrom(abstractMessage.toByteString()));
+
+ assertEquals(TestUtil.getPackedSet().toByteString(),
+ abstractMessage.toByteString());
+ }
+
+ public void testPackedParsing() throws Exception {
+ AbstractMessageWrapper.Builder builder =
+ new AbstractMessageWrapper.Builder(TestPackedTypes.newBuilder());
+ AbstractMessageWrapper message =
+ builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build();
+ TestUtil.assertPackedFieldsSet((TestPackedTypes) message.wrappedMessage);
+ }
+
public void testOptimizedForSize() throws Exception {
// We're mostly only checking that this class was compiled successfully.
TestOptimizedForSize message =
diff --git a/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java b/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java
index 5a96e3e6..c42b485c 100644
--- a/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java
+++ b/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java
@@ -31,6 +31,7 @@
package com.google.protobuf;
import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
import junit.framework.TestCase;
@@ -290,4 +291,14 @@ public class CodedOutputStreamTest extends TestCase {
assertEqualBytes(rawBytes, rawOutput.toByteArray());
}
}
+
+ /** Tests writing a whole message with every packed field type. Ensures the
+ * wire format of packed fields is compatible with C++. */
+ public void testWriteWholePackedFieldsMessage() throws Exception {
+ TestPackedTypes message = TestUtil.getPackedSet();
+
+ byte[] rawBytes = message.toByteArray();
+ assertEqualBytes(TestUtil.getGoldenPackedFieldsMessage().toByteArray(),
+ rawBytes);
+ }
}
diff --git a/java/src/test/java/com/google/protobuf/DynamicMessageTest.java b/java/src/test/java/com/google/protobuf/DynamicMessageTest.java
index e2c15c64..fc53c531 100644
--- a/java/src/test/java/com/google/protobuf/DynamicMessageTest.java
+++ b/java/src/test/java/com/google/protobuf/DynamicMessageTest.java
@@ -32,8 +32,10 @@ package com.google.protobuf;
import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
import junit.framework.TestCase;
+import java.util.Arrays;
/**
* Unit test for {@link DynamicMessage}. See also {@link MessageTest}, which
@@ -48,6 +50,8 @@ public class DynamicMessageTest extends TestCase {
TestUtil.ReflectionTester extensionsReflectionTester =
new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(),
TestUtil.getExtensionRegistry());
+ TestUtil.ReflectionTester packedReflectionTester =
+ new TestUtil.ReflectionTester(TestPackedTypes.getDescriptor(), null);
public void testDynamicMessageAccessors() throws Exception {
Message.Builder builder =
@@ -57,6 +61,12 @@ public class DynamicMessageTest extends TestCase {
reflectionTester.assertAllFieldsSetViaReflection(message);
}
+ public void testDynamicMessageSettersRejectNull() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ reflectionTester.assertReflectionSettersRejectNull(builder);
+ }
+
public void testDynamicMessageExtensionAccessors() throws Exception {
// We don't need to extensively test DynamicMessage's handling of
// extensions because, frankly, it doesn't do anything special with them.
@@ -68,6 +78,12 @@ public class DynamicMessageTest extends TestCase {
extensionsReflectionTester.assertAllFieldsSetViaReflection(message);
}
+ public void testDynamicMessageExtensionSettersRejectNull() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllExtensions.getDescriptor());
+ extensionsReflectionTester.assertReflectionSettersRejectNull(builder);
+ }
+
public void testDynamicMessageRepeatedSetters() throws Exception {
Message.Builder builder =
DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
@@ -77,6 +93,12 @@ public class DynamicMessageTest extends TestCase {
reflectionTester.assertRepeatedFieldsModifiedViaReflection(message);
}
+ public void testDynamicMessageRepeatedSettersRejectNull() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ reflectionTester.assertReflectionRepeatedSettersRejectNull(builder);
+ }
+
public void testDynamicMessageDefaults() throws Exception {
reflectionTester.assertClearViaReflection(
DynamicMessage.getDefaultInstance(TestAllTypes.getDescriptor()));
@@ -123,6 +145,33 @@ public class DynamicMessageTest extends TestCase {
reflectionTester.assertAllFieldsSetViaReflection(message2);
}
+ public void testDynamicMessagePackedSerialization() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestPackedTypes.getDescriptor());
+ packedReflectionTester.setPackedFieldsViaReflection(builder);
+ Message message = builder.build();
+
+ ByteString rawBytes = message.toByteString();
+ TestPackedTypes message2 = TestPackedTypes.parseFrom(rawBytes);
+
+ TestUtil.assertPackedFieldsSet(message2);
+
+ // In fact, the serialized forms should be exactly the same, byte-for-byte.
+ assertEquals(TestUtil.getPackedSet().toByteString(), rawBytes);
+ }
+
+ public void testDynamicMessagePackedParsing() throws Exception {
+ TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
+ TestUtil.setPackedFields(builder);
+ TestPackedTypes message = builder.build();
+
+ ByteString rawBytes = message.toByteString();
+
+ Message message2 =
+ DynamicMessage.parseFrom(TestPackedTypes.getDescriptor(), rawBytes);
+ packedReflectionTester.assertPackedFieldsSetViaReflection(message2);
+ }
+
public void testDynamicMessageCopy() throws Exception {
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
TestUtil.setAllFields(builder);
@@ -131,4 +180,23 @@ public class DynamicMessageTest extends TestCase {
DynamicMessage copy = DynamicMessage.newBuilder(message).build();
reflectionTester.assertAllFieldsSetViaReflection(copy);
}
+
+ public void testToBuilder() throws Exception {
+ DynamicMessage.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ reflectionTester.setAllFieldsViaReflection(builder);
+ int unknownFieldNum = 9;
+ long unknownFieldVal = 90;
+ builder.setUnknownFields(UnknownFieldSet.newBuilder()
+ .addField(unknownFieldNum,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(unknownFieldVal).build())
+ .build());
+ DynamicMessage message = builder.build();
+
+ DynamicMessage derived = message.toBuilder().build();
+ reflectionTester.assertAllFieldsSetViaReflection(derived);
+ assertEquals(Arrays.asList(unknownFieldVal),
+ derived.getUnknownFields().getField(unknownFieldNum).getVarintList());
+ }
}
diff --git a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
index 95c269a2..0ecdc6ae 100644
--- a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
+++ b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -71,6 +71,72 @@ public class GeneratedMessageTest extends TestCase {
TestUtil.assertAllFieldsSet(message);
}
+ public void testSettersRejectNull() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ try {
+ builder.setOptionalString(null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setOptionalBytes(null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setOptionalNestedMessage((TestAllTypes.NestedMessage) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setOptionalNestedMessage(
+ (TestAllTypes.NestedMessage.Builder) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setOptionalNestedEnum(null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedString(null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedBytes(null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedNestedMessage((TestAllTypes.NestedMessage) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedNestedMessage(
+ (TestAllTypes.NestedMessage.Builder) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedNestedEnum(null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ }
+
public void testRepeatedSetters() throws Exception {
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
TestUtil.setAllFields(builder);
@@ -79,6 +145,55 @@ public class GeneratedMessageTest extends TestCase {
TestUtil.assertRepeatedFieldsModified(message);
}
+ public void testRepeatedSettersRejectNull() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+
+ builder.addRepeatedString("one");
+ builder.addRepeatedString("two");
+ try {
+ builder.setRepeatedString(1, null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ builder.addRepeatedBytes(TestUtil.toBytes("one"));
+ builder.addRepeatedBytes(TestUtil.toBytes("two"));
+ try {
+ builder.setRepeatedBytes(1, null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ builder.addRepeatedNestedMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(218).build());
+ builder.addRepeatedNestedMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(456).build());
+ try {
+ builder.setRepeatedNestedMessage(1, (TestAllTypes.NestedMessage) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setRepeatedNestedMessage(
+ 1, (TestAllTypes.NestedMessage.Builder) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.FOO);
+ builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAR);
+ try {
+ builder.setRepeatedNestedEnum(1, null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ }
+
public void testRepeatedAppend() throws Exception {
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
@@ -97,6 +212,42 @@ public class GeneratedMessageTest extends TestCase {
assertEquals(12, message.getRepeatedForeignMessage(0).getC());
}
+ public void testRepeatedAppendRejectsNull() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+
+ ForeignMessage foreignMessage =
+ ForeignMessage.newBuilder().setC(12).build();
+ try {
+ builder.addAllRepeatedForeignMessage(
+ Arrays.asList(foreignMessage, (ForeignMessage) null));
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ try {
+ builder.addAllRepeatedForeignEnum(
+ Arrays.asList(ForeignEnum.FOREIGN_BAZ, null));
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ try {
+ builder.addAllRepeatedString(Arrays.asList("one", null));
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ try {
+ builder.addAllRepeatedBytes(Arrays.asList(TestUtil.toBytes("one"), null));
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ }
+
public void testSettingForeignMessageUsingBuilder() throws Exception {
TestAllTypes message = TestAllTypes.newBuilder()
// Pass builder for foreign message instance.
@@ -146,6 +297,11 @@ public class GeneratedMessageTest extends TestCase {
TestUtil.assertAllFieldsSet(message);
}
+ public void testReflectionSettersRejectNull() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ reflectionTester.assertReflectionSettersRejectNull(builder);
+ }
+
public void testReflectionRepeatedSetters() throws Exception {
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
reflectionTester.setAllFieldsViaReflection(builder);
@@ -154,6 +310,11 @@ public class GeneratedMessageTest extends TestCase {
TestUtil.assertRepeatedFieldsModified(message);
}
+ public void testReflectionRepeatedSettersRejectNull() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ reflectionTester.assertReflectionRepeatedSettersRejectNull(builder);
+ }
+
public void testReflectionDefaults() throws Exception {
reflectionTester.assertClearViaReflection(
TestAllTypes.getDefaultInstance());
@@ -161,6 +322,11 @@ public class GeneratedMessageTest extends TestCase {
TestAllTypes.newBuilder().build());
}
+ public void testEnumInterface() throws Exception {
+ assertTrue(TestAllTypes.getDefaultInstance().getDefaultNestedEnum()
+ instanceof ProtocolMessageEnum);
+ }
+
// =================================================================
// Extensions.
@@ -202,6 +368,11 @@ public class GeneratedMessageTest extends TestCase {
TestUtil.assertAllExtensionsSet(message);
}
+ public void testExtensionReflectionSettersRejectNull() throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ extensionsReflectionTester.assertReflectionSettersRejectNull(builder);
+ }
+
public void testExtensionReflectionRepeatedSetters() throws Exception {
TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
extensionsReflectionTester.setAllFieldsViaReflection(builder);
@@ -210,6 +381,13 @@ public class GeneratedMessageTest extends TestCase {
TestUtil.assertRepeatedExtensionsModified(message);
}
+ public void testExtensionReflectionRepeatedSettersRejectNull()
+ throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ extensionsReflectionTester.assertReflectionRepeatedSettersRejectNull(
+ builder);
+ }
+
public void testExtensionReflectionDefaults() throws Exception {
extensionsReflectionTester.assertClearViaReflection(
TestAllExtensions.getDefaultInstance());
@@ -231,6 +409,17 @@ public class GeneratedMessageTest extends TestCase {
.getExtensionCount(UnittestProto.repeatedInt32Extension));
}
+ public void testExtensionMergeFrom() throws Exception {
+ TestAllExtensions original =
+ TestAllExtensions.newBuilder()
+ .setExtension(UnittestProto.optionalInt32Extension, 1).build();
+ TestAllExtensions merged =
+ TestAllExtensions.newBuilder().mergeFrom(original).build();
+ assertTrue(merged.hasExtension(UnittestProto.optionalInt32Extension));
+ assertEquals(
+ 1, (int) merged.getExtension(UnittestProto.optionalInt32Extension));
+ }
+
// =================================================================
// multiple_files_test
@@ -266,7 +455,7 @@ public class GeneratedMessageTest extends TestCase {
TestOptionalOptimizedForSize message =
TestOptionalOptimizedForSize.getDefaultInstance();
assertTrue(message.isInitialized());
-
+
message = TestOptionalOptimizedForSize.newBuilder().setO(
TestRequiredOptimizedForSize.newBuilder().buildPartial()
).buildPartial();
@@ -292,4 +481,11 @@ public class GeneratedMessageTest extends TestCase {
assertTrue(builder.isInitialized());
assertTrue(builder.buildPartial().isInitialized());
}
+
+ public void testToBuilder() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestAllTypes message = builder.build();
+ TestUtil.assertAllFieldsSet(message.toBuilder().build());
+ }
}
diff --git a/java/src/test/java/com/google/protobuf/TestUtil.java b/java/src/test/java/com/google/protobuf/TestUtil.java
index d99ab85e..2f47b714 100644
--- a/java/src/test/java/com/google/protobuf/TestUtil.java
+++ b/java/src/test/java/com/google/protobuf/TestUtil.java
@@ -28,17 +28,105 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Note: This file contains many lines over 80 characters. It even contains
-// many lines over 100 characters, which fails a presubmit test. However,
-// given the extremely repetitive nature of the file, I (kenton) feel that
-// having similar components of each statement line up is more important than
-// avoiding horizontal scrolling. So, I am bypassing the presubmit check.
-
package com.google.protobuf;
import protobuf_unittest.UnittestProto;
-import protobuf_unittest.UnittestProto.TestAllTypes;
+
+// The static imports are to avoid 100+ char lines. The following is roughly equivalent to
+// import static protobuf_unittest.UnittestProto.*;
+import static protobuf_unittest.UnittestProto.defaultInt32Extension;
+import static protobuf_unittest.UnittestProto.defaultInt64Extension;
+import static protobuf_unittest.UnittestProto.defaultUint32Extension;
+import static protobuf_unittest.UnittestProto.defaultUint64Extension;
+import static protobuf_unittest.UnittestProto.defaultSint32Extension;
+import static protobuf_unittest.UnittestProto.defaultSint64Extension;
+import static protobuf_unittest.UnittestProto.defaultFixed32Extension;
+import static protobuf_unittest.UnittestProto.defaultFixed64Extension;
+import static protobuf_unittest.UnittestProto.defaultSfixed32Extension;
+import static protobuf_unittest.UnittestProto.defaultSfixed64Extension;
+import static protobuf_unittest.UnittestProto.defaultFloatExtension;
+import static protobuf_unittest.UnittestProto.defaultDoubleExtension;
+import static protobuf_unittest.UnittestProto.defaultBoolExtension;
+import static protobuf_unittest.UnittestProto.defaultStringExtension;
+import static protobuf_unittest.UnittestProto.defaultBytesExtension;
+import static protobuf_unittest.UnittestProto.defaultNestedEnumExtension;
+import static protobuf_unittest.UnittestProto.defaultForeignEnumExtension;
+import static protobuf_unittest.UnittestProto.defaultImportEnumExtension;
+import static protobuf_unittest.UnittestProto.defaultStringPieceExtension;
+import static protobuf_unittest.UnittestProto.defaultCordExtension;
+
+import static protobuf_unittest.UnittestProto.optionalInt32Extension;
+import static protobuf_unittest.UnittestProto.optionalInt64Extension;
+import static protobuf_unittest.UnittestProto.optionalUint32Extension;
+import static protobuf_unittest.UnittestProto.optionalUint64Extension;
+import static protobuf_unittest.UnittestProto.optionalSint32Extension;
+import static protobuf_unittest.UnittestProto.optionalSint64Extension;
+import static protobuf_unittest.UnittestProto.optionalFixed32Extension;
+import static protobuf_unittest.UnittestProto.optionalFixed64Extension;
+import static protobuf_unittest.UnittestProto.optionalSfixed32Extension;
+import static protobuf_unittest.UnittestProto.optionalSfixed64Extension;
+import static protobuf_unittest.UnittestProto.optionalFloatExtension;
+import static protobuf_unittest.UnittestProto.optionalDoubleExtension;
+import static protobuf_unittest.UnittestProto.optionalBoolExtension;
+import static protobuf_unittest.UnittestProto.optionalStringExtension;
+import static protobuf_unittest.UnittestProto.optionalBytesExtension;
+import static protobuf_unittest.UnittestProto.optionalGroupExtension;
+import static protobuf_unittest.UnittestProto.optionalNestedMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalForeignMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalImportMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalNestedEnumExtension;
+import static protobuf_unittest.UnittestProto.optionalForeignEnumExtension;
+import static protobuf_unittest.UnittestProto.optionalImportEnumExtension;
+import static protobuf_unittest.UnittestProto.optionalStringPieceExtension;
+import static protobuf_unittest.UnittestProto.optionalCordExtension;
+
+import static protobuf_unittest.UnittestProto.repeatedInt32Extension;
+import static protobuf_unittest.UnittestProto.repeatedInt64Extension;
+import static protobuf_unittest.UnittestProto.repeatedUint32Extension;
+import static protobuf_unittest.UnittestProto.repeatedUint64Extension;
+import static protobuf_unittest.UnittestProto.repeatedSint32Extension;
+import static protobuf_unittest.UnittestProto.repeatedSint64Extension;
+import static protobuf_unittest.UnittestProto.repeatedFixed32Extension;
+import static protobuf_unittest.UnittestProto.repeatedFixed64Extension;
+import static protobuf_unittest.UnittestProto.repeatedSfixed32Extension;
+import static protobuf_unittest.UnittestProto.repeatedSfixed64Extension;
+import static protobuf_unittest.UnittestProto.repeatedFloatExtension;
+import static protobuf_unittest.UnittestProto.repeatedDoubleExtension;
+import static protobuf_unittest.UnittestProto.repeatedBoolExtension;
+import static protobuf_unittest.UnittestProto.repeatedStringExtension;
+import static protobuf_unittest.UnittestProto.repeatedBytesExtension;
+import static protobuf_unittest.UnittestProto.repeatedGroupExtension;
+import static protobuf_unittest.UnittestProto.repeatedNestedMessageExtension;
+import static protobuf_unittest.UnittestProto.repeatedForeignMessageExtension;
+import static protobuf_unittest.UnittestProto.repeatedImportMessageExtension;
+import static protobuf_unittest.UnittestProto.repeatedNestedEnumExtension;
+import static protobuf_unittest.UnittestProto.repeatedForeignEnumExtension;
+import static protobuf_unittest.UnittestProto.repeatedImportEnumExtension;
+import static protobuf_unittest.UnittestProto.repeatedStringPieceExtension;
+import static protobuf_unittest.UnittestProto.repeatedCordExtension;
+
+import static protobuf_unittest.UnittestProto.OptionalGroup_extension;
+import static protobuf_unittest.UnittestProto.RepeatedGroup_extension;
+
+import static protobuf_unittest.UnittestProto.packedInt32Extension;
+import static protobuf_unittest.UnittestProto.packedInt64Extension;
+import static protobuf_unittest.UnittestProto.packedUint32Extension;
+import static protobuf_unittest.UnittestProto.packedUint64Extension;
+import static protobuf_unittest.UnittestProto.packedSint32Extension;
+import static protobuf_unittest.UnittestProto.packedSint64Extension;
+import static protobuf_unittest.UnittestProto.packedFixed32Extension;
+import static protobuf_unittest.UnittestProto.packedFixed64Extension;
+import static protobuf_unittest.UnittestProto.packedSfixed32Extension;
+import static protobuf_unittest.UnittestProto.packedSfixed64Extension;
+import static protobuf_unittest.UnittestProto.packedFloatExtension;
+import static protobuf_unittest.UnittestProto.packedDoubleExtension;
+import static protobuf_unittest.UnittestProto.packedBoolExtension;
+import static protobuf_unittest.UnittestProto.packedEnumExtension;
+
import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestPackedExtensions;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
import protobuf_unittest.UnittestProto.ForeignMessage;
import protobuf_unittest.UnittestProto.ForeignEnum;
import com.google.protobuf.test.UnittestImport.ImportMessage;
@@ -63,7 +151,7 @@ class TestUtil {
private TestUtil() {}
/** Helper to convert a String to ByteString. */
- private static ByteString toBytes(String str) {
+ static ByteString toBytes(String str) {
try {
return ByteString.copyFrom(str.getBytes("UTF-8"));
} catch(java.io.UnsupportedEncodingException e) {
@@ -91,6 +179,18 @@ class TestUtil {
return builder.build();
}
+ public static TestPackedTypes getPackedSet() {
+ TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
+ setPackedFields(builder);
+ return builder.build();
+ }
+
+ public static TestPackedExtensions getPackedExtensionsSet() {
+ TestPackedExtensions.Builder builder = TestPackedExtensions.newBuilder();
+ setPackedExtensions(builder);
+ return builder.build();
+ }
+
/**
* Set every field of {@code message} to the values expected by
* {@code assertAllFieldsSet()}.
@@ -770,141 +870,129 @@ class TestUtil {
* {@code assertAllExtensionsSet()}.
*/
public static void setAllExtensions(TestAllExtensions.Builder message) {
- message.setExtension(UnittestProto.optionalInt32Extension , 101);
- message.setExtension(UnittestProto.optionalInt64Extension , 102L);
- message.setExtension(UnittestProto.optionalUint32Extension , 103);
- message.setExtension(UnittestProto.optionalUint64Extension , 104L);
- message.setExtension(UnittestProto.optionalSint32Extension , 105);
- message.setExtension(UnittestProto.optionalSint64Extension , 106L);
- message.setExtension(UnittestProto.optionalFixed32Extension , 107);
- message.setExtension(UnittestProto.optionalFixed64Extension , 108L);
- message.setExtension(UnittestProto.optionalSfixed32Extension, 109);
- message.setExtension(UnittestProto.optionalSfixed64Extension, 110L);
- message.setExtension(UnittestProto.optionalFloatExtension , 111F);
- message.setExtension(UnittestProto.optionalDoubleExtension , 112D);
- message.setExtension(UnittestProto.optionalBoolExtension , true);
- message.setExtension(UnittestProto.optionalStringExtension , "115");
- message.setExtension(UnittestProto.optionalBytesExtension , toBytes("116"));
-
- message.setExtension(UnittestProto.optionalGroupExtension,
- UnittestProto.OptionalGroup_extension.newBuilder().setA(117).build());
- message.setExtension(UnittestProto.optionalNestedMessageExtension,
+ message.setExtension(optionalInt32Extension , 101);
+ message.setExtension(optionalInt64Extension , 102L);
+ message.setExtension(optionalUint32Extension , 103);
+ message.setExtension(optionalUint64Extension , 104L);
+ message.setExtension(optionalSint32Extension , 105);
+ message.setExtension(optionalSint64Extension , 106L);
+ message.setExtension(optionalFixed32Extension , 107);
+ message.setExtension(optionalFixed64Extension , 108L);
+ message.setExtension(optionalSfixed32Extension, 109);
+ message.setExtension(optionalSfixed64Extension, 110L);
+ message.setExtension(optionalFloatExtension , 111F);
+ message.setExtension(optionalDoubleExtension , 112D);
+ message.setExtension(optionalBoolExtension , true);
+ message.setExtension(optionalStringExtension , "115");
+ message.setExtension(optionalBytesExtension , toBytes("116"));
+
+ message.setExtension(optionalGroupExtension,
+ OptionalGroup_extension.newBuilder().setA(117).build());
+ message.setExtension(optionalNestedMessageExtension,
TestAllTypes.NestedMessage.newBuilder().setBb(118).build());
- message.setExtension(UnittestProto.optionalForeignMessageExtension,
+ message.setExtension(optionalForeignMessageExtension,
ForeignMessage.newBuilder().setC(119).build());
- message.setExtension(UnittestProto.optionalImportMessageExtension,
+ message.setExtension(optionalImportMessageExtension,
ImportMessage.newBuilder().setD(120).build());
- message.setExtension(UnittestProto.optionalNestedEnumExtension,
- TestAllTypes.NestedEnum.BAZ);
- message.setExtension(UnittestProto.optionalForeignEnumExtension,
- ForeignEnum.FOREIGN_BAZ);
- message.setExtension(UnittestProto.optionalImportEnumExtension,
- ImportEnum.IMPORT_BAZ);
+ message.setExtension(optionalNestedEnumExtension, TestAllTypes.NestedEnum.BAZ);
+ message.setExtension(optionalForeignEnumExtension, ForeignEnum.FOREIGN_BAZ);
+ message.setExtension(optionalImportEnumExtension, ImportEnum.IMPORT_BAZ);
- message.setExtension(UnittestProto.optionalStringPieceExtension, "124");
- message.setExtension(UnittestProto.optionalCordExtension, "125");
+ message.setExtension(optionalStringPieceExtension, "124");
+ message.setExtension(optionalCordExtension, "125");
// -----------------------------------------------------------------
- message.addExtension(UnittestProto.repeatedInt32Extension , 201);
- message.addExtension(UnittestProto.repeatedInt64Extension , 202L);
- message.addExtension(UnittestProto.repeatedUint32Extension , 203);
- message.addExtension(UnittestProto.repeatedUint64Extension , 204L);
- message.addExtension(UnittestProto.repeatedSint32Extension , 205);
- message.addExtension(UnittestProto.repeatedSint64Extension , 206L);
- message.addExtension(UnittestProto.repeatedFixed32Extension , 207);
- message.addExtension(UnittestProto.repeatedFixed64Extension , 208L);
- message.addExtension(UnittestProto.repeatedSfixed32Extension, 209);
- message.addExtension(UnittestProto.repeatedSfixed64Extension, 210L);
- message.addExtension(UnittestProto.repeatedFloatExtension , 211F);
- message.addExtension(UnittestProto.repeatedDoubleExtension , 212D);
- message.addExtension(UnittestProto.repeatedBoolExtension , true);
- message.addExtension(UnittestProto.repeatedStringExtension , "215");
- message.addExtension(UnittestProto.repeatedBytesExtension , toBytes("216"));
-
- message.addExtension(UnittestProto.repeatedGroupExtension,
- UnittestProto.RepeatedGroup_extension.newBuilder().setA(217).build());
- message.addExtension(UnittestProto.repeatedNestedMessageExtension,
+ message.addExtension(repeatedInt32Extension , 201);
+ message.addExtension(repeatedInt64Extension , 202L);
+ message.addExtension(repeatedUint32Extension , 203);
+ message.addExtension(repeatedUint64Extension , 204L);
+ message.addExtension(repeatedSint32Extension , 205);
+ message.addExtension(repeatedSint64Extension , 206L);
+ message.addExtension(repeatedFixed32Extension , 207);
+ message.addExtension(repeatedFixed64Extension , 208L);
+ message.addExtension(repeatedSfixed32Extension, 209);
+ message.addExtension(repeatedSfixed64Extension, 210L);
+ message.addExtension(repeatedFloatExtension , 211F);
+ message.addExtension(repeatedDoubleExtension , 212D);
+ message.addExtension(repeatedBoolExtension , true);
+ message.addExtension(repeatedStringExtension , "215");
+ message.addExtension(repeatedBytesExtension , toBytes("216"));
+
+ message.addExtension(repeatedGroupExtension,
+ RepeatedGroup_extension.newBuilder().setA(217).build());
+ message.addExtension(repeatedNestedMessageExtension,
TestAllTypes.NestedMessage.newBuilder().setBb(218).build());
- message.addExtension(UnittestProto.repeatedForeignMessageExtension,
+ message.addExtension(repeatedForeignMessageExtension,
ForeignMessage.newBuilder().setC(219).build());
- message.addExtension(UnittestProto.repeatedImportMessageExtension,
+ message.addExtension(repeatedImportMessageExtension,
ImportMessage.newBuilder().setD(220).build());
- message.addExtension(UnittestProto.repeatedNestedEnumExtension,
- TestAllTypes.NestedEnum.BAR);
- message.addExtension(UnittestProto.repeatedForeignEnumExtension,
- ForeignEnum.FOREIGN_BAR);
- message.addExtension(UnittestProto.repeatedImportEnumExtension,
- ImportEnum.IMPORT_BAR);
+ message.addExtension(repeatedNestedEnumExtension, TestAllTypes.NestedEnum.BAR);
+ message.addExtension(repeatedForeignEnumExtension, ForeignEnum.FOREIGN_BAR);
+ message.addExtension(repeatedImportEnumExtension, ImportEnum.IMPORT_BAR);
- message.addExtension(UnittestProto.repeatedStringPieceExtension, "224");
- message.addExtension(UnittestProto.repeatedCordExtension, "225");
+ message.addExtension(repeatedStringPieceExtension, "224");
+ message.addExtension(repeatedCordExtension, "225");
// Add a second one of each field.
- message.addExtension(UnittestProto.repeatedInt32Extension , 301);
- message.addExtension(UnittestProto.repeatedInt64Extension , 302L);
- message.addExtension(UnittestProto.repeatedUint32Extension , 303);
- message.addExtension(UnittestProto.repeatedUint64Extension , 304L);
- message.addExtension(UnittestProto.repeatedSint32Extension , 305);
- message.addExtension(UnittestProto.repeatedSint64Extension , 306L);
- message.addExtension(UnittestProto.repeatedFixed32Extension , 307);
- message.addExtension(UnittestProto.repeatedFixed64Extension , 308L);
- message.addExtension(UnittestProto.repeatedSfixed32Extension, 309);
- message.addExtension(UnittestProto.repeatedSfixed64Extension, 310L);
- message.addExtension(UnittestProto.repeatedFloatExtension , 311F);
- message.addExtension(UnittestProto.repeatedDoubleExtension , 312D);
- message.addExtension(UnittestProto.repeatedBoolExtension , false);
- message.addExtension(UnittestProto.repeatedStringExtension , "315");
- message.addExtension(UnittestProto.repeatedBytesExtension , toBytes("316"));
-
- message.addExtension(UnittestProto.repeatedGroupExtension,
- UnittestProto.RepeatedGroup_extension.newBuilder().setA(317).build());
- message.addExtension(UnittestProto.repeatedNestedMessageExtension,
+ message.addExtension(repeatedInt32Extension , 301);
+ message.addExtension(repeatedInt64Extension , 302L);
+ message.addExtension(repeatedUint32Extension , 303);
+ message.addExtension(repeatedUint64Extension , 304L);
+ message.addExtension(repeatedSint32Extension , 305);
+ message.addExtension(repeatedSint64Extension , 306L);
+ message.addExtension(repeatedFixed32Extension , 307);
+ message.addExtension(repeatedFixed64Extension , 308L);
+ message.addExtension(repeatedSfixed32Extension, 309);
+ message.addExtension(repeatedSfixed64Extension, 310L);
+ message.addExtension(repeatedFloatExtension , 311F);
+ message.addExtension(repeatedDoubleExtension , 312D);
+ message.addExtension(repeatedBoolExtension , false);
+ message.addExtension(repeatedStringExtension , "315");
+ message.addExtension(repeatedBytesExtension , toBytes("316"));
+
+ message.addExtension(repeatedGroupExtension,
+ RepeatedGroup_extension.newBuilder().setA(317).build());
+ message.addExtension(repeatedNestedMessageExtension,
TestAllTypes.NestedMessage.newBuilder().setBb(318).build());
- message.addExtension(UnittestProto.repeatedForeignMessageExtension,
+ message.addExtension(repeatedForeignMessageExtension,
ForeignMessage.newBuilder().setC(319).build());
- message.addExtension(UnittestProto.repeatedImportMessageExtension,
+ message.addExtension(repeatedImportMessageExtension,
ImportMessage.newBuilder().setD(320).build());
- message.addExtension(UnittestProto.repeatedNestedEnumExtension,
- TestAllTypes.NestedEnum.BAZ);
- message.addExtension(UnittestProto.repeatedForeignEnumExtension,
- ForeignEnum.FOREIGN_BAZ);
- message.addExtension(UnittestProto.repeatedImportEnumExtension,
- ImportEnum.IMPORT_BAZ);
+ message.addExtension(repeatedNestedEnumExtension, TestAllTypes.NestedEnum.BAZ);
+ message.addExtension(repeatedForeignEnumExtension, ForeignEnum.FOREIGN_BAZ);
+ message.addExtension(repeatedImportEnumExtension, ImportEnum.IMPORT_BAZ);
- message.addExtension(UnittestProto.repeatedStringPieceExtension, "324");
- message.addExtension(UnittestProto.repeatedCordExtension, "325");
+ message.addExtension(repeatedStringPieceExtension, "324");
+ message.addExtension(repeatedCordExtension, "325");
// -----------------------------------------------------------------
- message.setExtension(UnittestProto.defaultInt32Extension , 401);
- message.setExtension(UnittestProto.defaultInt64Extension , 402L);
- message.setExtension(UnittestProto.defaultUint32Extension , 403);
- message.setExtension(UnittestProto.defaultUint64Extension , 404L);
- message.setExtension(UnittestProto.defaultSint32Extension , 405);
- message.setExtension(UnittestProto.defaultSint64Extension , 406L);
- message.setExtension(UnittestProto.defaultFixed32Extension , 407);
- message.setExtension(UnittestProto.defaultFixed64Extension , 408L);
- message.setExtension(UnittestProto.defaultSfixed32Extension, 409);
- message.setExtension(UnittestProto.defaultSfixed64Extension, 410L);
- message.setExtension(UnittestProto.defaultFloatExtension , 411F);
- message.setExtension(UnittestProto.defaultDoubleExtension , 412D);
- message.setExtension(UnittestProto.defaultBoolExtension , false);
- message.setExtension(UnittestProto.defaultStringExtension , "415");
- message.setExtension(UnittestProto.defaultBytesExtension , toBytes("416"));
-
- message.setExtension(UnittestProto.defaultNestedEnumExtension,
- TestAllTypes.NestedEnum.FOO);
- message.setExtension(UnittestProto.defaultForeignEnumExtension,
- ForeignEnum.FOREIGN_FOO);
- message.setExtension(UnittestProto.defaultImportEnumExtension,
- ImportEnum.IMPORT_FOO);
-
- message.setExtension(UnittestProto.defaultStringPieceExtension, "424");
- message.setExtension(UnittestProto.defaultCordExtension, "425");
+ message.setExtension(defaultInt32Extension , 401);
+ message.setExtension(defaultInt64Extension , 402L);
+ message.setExtension(defaultUint32Extension , 403);
+ message.setExtension(defaultUint64Extension , 404L);
+ message.setExtension(defaultSint32Extension , 405);
+ message.setExtension(defaultSint64Extension , 406L);
+ message.setExtension(defaultFixed32Extension , 407);
+ message.setExtension(defaultFixed64Extension , 408L);
+ message.setExtension(defaultSfixed32Extension, 409);
+ message.setExtension(defaultSfixed64Extension, 410L);
+ message.setExtension(defaultFloatExtension , 411F);
+ message.setExtension(defaultDoubleExtension , 412D);
+ message.setExtension(defaultBoolExtension , false);
+ message.setExtension(defaultStringExtension , "415");
+ message.setExtension(defaultBytesExtension , toBytes("416"));
+
+ message.setExtension(defaultNestedEnumExtension, TestAllTypes.NestedEnum.FOO);
+ message.setExtension(defaultForeignEnumExtension, ForeignEnum.FOREIGN_FOO);
+ message.setExtension(defaultImportEnumExtension, ImportEnum.IMPORT_FOO);
+
+ message.setExtension(defaultStringPieceExtension, "424");
+ message.setExtension(defaultCordExtension, "425");
}
// -------------------------------------------------------------------
@@ -915,40 +1003,37 @@ class TestUtil {
*/
public static void modifyRepeatedExtensions(
TestAllExtensions.Builder message) {
- message.setExtension(UnittestProto.repeatedInt32Extension , 1, 501);
- message.setExtension(UnittestProto.repeatedInt64Extension , 1, 502L);
- message.setExtension(UnittestProto.repeatedUint32Extension , 1, 503);
- message.setExtension(UnittestProto.repeatedUint64Extension , 1, 504L);
- message.setExtension(UnittestProto.repeatedSint32Extension , 1, 505);
- message.setExtension(UnittestProto.repeatedSint64Extension , 1, 506L);
- message.setExtension(UnittestProto.repeatedFixed32Extension , 1, 507);
- message.setExtension(UnittestProto.repeatedFixed64Extension , 1, 508L);
- message.setExtension(UnittestProto.repeatedSfixed32Extension, 1, 509);
- message.setExtension(UnittestProto.repeatedSfixed64Extension, 1, 510L);
- message.setExtension(UnittestProto.repeatedFloatExtension , 1, 511F);
- message.setExtension(UnittestProto.repeatedDoubleExtension , 1, 512D);
- message.setExtension(UnittestProto.repeatedBoolExtension , 1, true);
- message.setExtension(UnittestProto.repeatedStringExtension , 1, "515");
- message.setExtension(UnittestProto.repeatedBytesExtension , 1, toBytes("516"));
-
- message.setExtension(UnittestProto.repeatedGroupExtension, 1,
- UnittestProto.RepeatedGroup_extension.newBuilder().setA(517).build());
- message.setExtension(UnittestProto.repeatedNestedMessageExtension, 1,
+ message.setExtension(repeatedInt32Extension , 1, 501);
+ message.setExtension(repeatedInt64Extension , 1, 502L);
+ message.setExtension(repeatedUint32Extension , 1, 503);
+ message.setExtension(repeatedUint64Extension , 1, 504L);
+ message.setExtension(repeatedSint32Extension , 1, 505);
+ message.setExtension(repeatedSint64Extension , 1, 506L);
+ message.setExtension(repeatedFixed32Extension , 1, 507);
+ message.setExtension(repeatedFixed64Extension , 1, 508L);
+ message.setExtension(repeatedSfixed32Extension, 1, 509);
+ message.setExtension(repeatedSfixed64Extension, 1, 510L);
+ message.setExtension(repeatedFloatExtension , 1, 511F);
+ message.setExtension(repeatedDoubleExtension , 1, 512D);
+ message.setExtension(repeatedBoolExtension , 1, true);
+ message.setExtension(repeatedStringExtension , 1, "515");
+ message.setExtension(repeatedBytesExtension , 1, toBytes("516"));
+
+ message.setExtension(repeatedGroupExtension, 1,
+ RepeatedGroup_extension.newBuilder().setA(517).build());
+ message.setExtension(repeatedNestedMessageExtension, 1,
TestAllTypes.NestedMessage.newBuilder().setBb(518).build());
- message.setExtension(UnittestProto.repeatedForeignMessageExtension, 1,
+ message.setExtension(repeatedForeignMessageExtension, 1,
ForeignMessage.newBuilder().setC(519).build());
- message.setExtension(UnittestProto.repeatedImportMessageExtension, 1,
+ message.setExtension(repeatedImportMessageExtension, 1,
ImportMessage.newBuilder().setD(520).build());
- message.setExtension(UnittestProto.repeatedNestedEnumExtension , 1,
- TestAllTypes.NestedEnum.FOO);
- message.setExtension(UnittestProto.repeatedForeignEnumExtension, 1,
- ForeignEnum.FOREIGN_FOO);
- message.setExtension(UnittestProto.repeatedImportEnumExtension , 1,
- ImportEnum.IMPORT_FOO);
+ message.setExtension(repeatedNestedEnumExtension , 1, TestAllTypes.NestedEnum.FOO);
+ message.setExtension(repeatedForeignEnumExtension, 1, ForeignEnum.FOREIGN_FOO);
+ message.setExtension(repeatedImportEnumExtension , 1, ImportEnum.IMPORT_FOO);
- message.setExtension(UnittestProto.repeatedStringPieceExtension, 1, "524");
- message.setExtension(UnittestProto.repeatedCordExtension, 1, "525");
+ message.setExtension(repeatedStringPieceExtension, 1, "524");
+ message.setExtension(repeatedCordExtension, 1, "525");
}
// -------------------------------------------------------------------
@@ -958,211 +1043,211 @@ class TestUtil {
* {@code message} are set to the values assigned by {@code setAllExtensions}.
*/
public static void assertAllExtensionsSet(TestAllExtensions message) {
- Assert.assertTrue(message.hasExtension(UnittestProto.optionalInt32Extension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.optionalInt64Extension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.optionalUint32Extension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.optionalUint64Extension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.optionalSint32Extension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.optionalSint64Extension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.optionalFixed32Extension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.optionalFixed64Extension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.optionalSfixed32Extension));
- Assert.assertTrue(message.hasExtension(UnittestProto.optionalSfixed64Extension));
- Assert.assertTrue(message.hasExtension(UnittestProto.optionalFloatExtension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.optionalDoubleExtension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.optionalBoolExtension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.optionalStringExtension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.optionalBytesExtension ));
-
- Assert.assertTrue(message.hasExtension(UnittestProto.optionalGroupExtension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.optionalNestedMessageExtension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.optionalForeignMessageExtension));
- Assert.assertTrue(message.hasExtension(UnittestProto.optionalImportMessageExtension ));
-
- Assert.assertTrue(message.getExtension(UnittestProto.optionalGroupExtension ).hasA());
- Assert.assertTrue(message.getExtension(UnittestProto.optionalNestedMessageExtension ).hasBb());
- Assert.assertTrue(message.getExtension(UnittestProto.optionalForeignMessageExtension).hasC());
- Assert.assertTrue(message.getExtension(UnittestProto.optionalImportMessageExtension ).hasD());
-
- Assert.assertTrue(message.hasExtension(UnittestProto.optionalNestedEnumExtension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.optionalForeignEnumExtension));
- Assert.assertTrue(message.hasExtension(UnittestProto.optionalImportEnumExtension ));
-
- Assert.assertTrue(message.hasExtension(UnittestProto.optionalStringPieceExtension));
- Assert.assertTrue(message.hasExtension(UnittestProto.optionalCordExtension));
-
- assertEqualsExactType(101 , message.getExtension(UnittestProto.optionalInt32Extension ));
- assertEqualsExactType(102L , message.getExtension(UnittestProto.optionalInt64Extension ));
- assertEqualsExactType(103 , message.getExtension(UnittestProto.optionalUint32Extension ));
- assertEqualsExactType(104L , message.getExtension(UnittestProto.optionalUint64Extension ));
- assertEqualsExactType(105 , message.getExtension(UnittestProto.optionalSint32Extension ));
- assertEqualsExactType(106L , message.getExtension(UnittestProto.optionalSint64Extension ));
- assertEqualsExactType(107 , message.getExtension(UnittestProto.optionalFixed32Extension ));
- assertEqualsExactType(108L , message.getExtension(UnittestProto.optionalFixed64Extension ));
- assertEqualsExactType(109 , message.getExtension(UnittestProto.optionalSfixed32Extension));
- assertEqualsExactType(110L , message.getExtension(UnittestProto.optionalSfixed64Extension));
- assertEqualsExactType(111F , message.getExtension(UnittestProto.optionalFloatExtension ));
- assertEqualsExactType(112D , message.getExtension(UnittestProto.optionalDoubleExtension ));
- assertEqualsExactType(true , message.getExtension(UnittestProto.optionalBoolExtension ));
- assertEqualsExactType("115", message.getExtension(UnittestProto.optionalStringExtension ));
- assertEqualsExactType(toBytes("116"), message.getExtension(UnittestProto.optionalBytesExtension));
-
- assertEqualsExactType(117, message.getExtension(UnittestProto.optionalGroupExtension ).getA());
- assertEqualsExactType(118, message.getExtension(UnittestProto.optionalNestedMessageExtension ).getBb());
- assertEqualsExactType(119, message.getExtension(UnittestProto.optionalForeignMessageExtension).getC());
- assertEqualsExactType(120, message.getExtension(UnittestProto.optionalImportMessageExtension ).getD());
+ Assert.assertTrue(message.hasExtension(optionalInt32Extension ));
+ Assert.assertTrue(message.hasExtension(optionalInt64Extension ));
+ Assert.assertTrue(message.hasExtension(optionalUint32Extension ));
+ Assert.assertTrue(message.hasExtension(optionalUint64Extension ));
+ Assert.assertTrue(message.hasExtension(optionalSint32Extension ));
+ Assert.assertTrue(message.hasExtension(optionalSint64Extension ));
+ Assert.assertTrue(message.hasExtension(optionalFixed32Extension ));
+ Assert.assertTrue(message.hasExtension(optionalFixed64Extension ));
+ Assert.assertTrue(message.hasExtension(optionalSfixed32Extension));
+ Assert.assertTrue(message.hasExtension(optionalSfixed64Extension));
+ Assert.assertTrue(message.hasExtension(optionalFloatExtension ));
+ Assert.assertTrue(message.hasExtension(optionalDoubleExtension ));
+ Assert.assertTrue(message.hasExtension(optionalBoolExtension ));
+ Assert.assertTrue(message.hasExtension(optionalStringExtension ));
+ Assert.assertTrue(message.hasExtension(optionalBytesExtension ));
+
+ Assert.assertTrue(message.hasExtension(optionalGroupExtension ));
+ Assert.assertTrue(message.hasExtension(optionalNestedMessageExtension ));
+ Assert.assertTrue(message.hasExtension(optionalForeignMessageExtension));
+ Assert.assertTrue(message.hasExtension(optionalImportMessageExtension ));
+
+ Assert.assertTrue(message.getExtension(optionalGroupExtension ).hasA());
+ Assert.assertTrue(message.getExtension(optionalNestedMessageExtension ).hasBb());
+ Assert.assertTrue(message.getExtension(optionalForeignMessageExtension).hasC());
+ Assert.assertTrue(message.getExtension(optionalImportMessageExtension ).hasD());
+
+ Assert.assertTrue(message.hasExtension(optionalNestedEnumExtension ));
+ Assert.assertTrue(message.hasExtension(optionalForeignEnumExtension));
+ Assert.assertTrue(message.hasExtension(optionalImportEnumExtension ));
+
+ Assert.assertTrue(message.hasExtension(optionalStringPieceExtension));
+ Assert.assertTrue(message.hasExtension(optionalCordExtension));
+
+ assertEqualsExactType(101 , message.getExtension(optionalInt32Extension ));
+ assertEqualsExactType(102L , message.getExtension(optionalInt64Extension ));
+ assertEqualsExactType(103 , message.getExtension(optionalUint32Extension ));
+ assertEqualsExactType(104L , message.getExtension(optionalUint64Extension ));
+ assertEqualsExactType(105 , message.getExtension(optionalSint32Extension ));
+ assertEqualsExactType(106L , message.getExtension(optionalSint64Extension ));
+ assertEqualsExactType(107 , message.getExtension(optionalFixed32Extension ));
+ assertEqualsExactType(108L , message.getExtension(optionalFixed64Extension ));
+ assertEqualsExactType(109 , message.getExtension(optionalSfixed32Extension));
+ assertEqualsExactType(110L , message.getExtension(optionalSfixed64Extension));
+ assertEqualsExactType(111F , message.getExtension(optionalFloatExtension ));
+ assertEqualsExactType(112D , message.getExtension(optionalDoubleExtension ));
+ assertEqualsExactType(true , message.getExtension(optionalBoolExtension ));
+ assertEqualsExactType("115", message.getExtension(optionalStringExtension ));
+ assertEqualsExactType(toBytes("116"), message.getExtension(optionalBytesExtension));
+
+ assertEqualsExactType(117, message.getExtension(optionalGroupExtension ).getA());
+ assertEqualsExactType(118, message.getExtension(optionalNestedMessageExtension ).getBb());
+ assertEqualsExactType(119, message.getExtension(optionalForeignMessageExtension).getC());
+ assertEqualsExactType(120, message.getExtension(optionalImportMessageExtension ).getD());
assertEqualsExactType(TestAllTypes.NestedEnum.BAZ,
- message.getExtension(UnittestProto.optionalNestedEnumExtension));
+ message.getExtension(optionalNestedEnumExtension));
assertEqualsExactType(ForeignEnum.FOREIGN_BAZ,
- message.getExtension(UnittestProto.optionalForeignEnumExtension));
+ message.getExtension(optionalForeignEnumExtension));
assertEqualsExactType(ImportEnum.IMPORT_BAZ,
- message.getExtension(UnittestProto.optionalImportEnumExtension));
+ message.getExtension(optionalImportEnumExtension));
- assertEqualsExactType("124", message.getExtension(UnittestProto.optionalStringPieceExtension));
- assertEqualsExactType("125", message.getExtension(UnittestProto.optionalCordExtension));
+ assertEqualsExactType("124", message.getExtension(optionalStringPieceExtension));
+ assertEqualsExactType("125", message.getExtension(optionalCordExtension));
// -----------------------------------------------------------------
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedInt32Extension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedInt64Extension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedUint32Extension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedUint64Extension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedSint32Extension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedSint64Extension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedFixed32Extension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedFixed64Extension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedSfixed32Extension));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedSfixed64Extension));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedFloatExtension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedDoubleExtension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedBoolExtension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedStringExtension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedBytesExtension ));
-
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedGroupExtension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedNestedMessageExtension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedForeignMessageExtension));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedImportMessageExtension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedNestedEnumExtension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedForeignEnumExtension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedImportEnumExtension ));
-
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedStringPieceExtension));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedCordExtension));
-
- assertEqualsExactType(201 , message.getExtension(UnittestProto.repeatedInt32Extension , 0));
- assertEqualsExactType(202L , message.getExtension(UnittestProto.repeatedInt64Extension , 0));
- assertEqualsExactType(203 , message.getExtension(UnittestProto.repeatedUint32Extension , 0));
- assertEqualsExactType(204L , message.getExtension(UnittestProto.repeatedUint64Extension , 0));
- assertEqualsExactType(205 , message.getExtension(UnittestProto.repeatedSint32Extension , 0));
- assertEqualsExactType(206L , message.getExtension(UnittestProto.repeatedSint64Extension , 0));
- assertEqualsExactType(207 , message.getExtension(UnittestProto.repeatedFixed32Extension , 0));
- assertEqualsExactType(208L , message.getExtension(UnittestProto.repeatedFixed64Extension , 0));
- assertEqualsExactType(209 , message.getExtension(UnittestProto.repeatedSfixed32Extension, 0));
- assertEqualsExactType(210L , message.getExtension(UnittestProto.repeatedSfixed64Extension, 0));
- assertEqualsExactType(211F , message.getExtension(UnittestProto.repeatedFloatExtension , 0));
- assertEqualsExactType(212D , message.getExtension(UnittestProto.repeatedDoubleExtension , 0));
- assertEqualsExactType(true , message.getExtension(UnittestProto.repeatedBoolExtension , 0));
- assertEqualsExactType("215", message.getExtension(UnittestProto.repeatedStringExtension , 0));
- assertEqualsExactType(toBytes("216"), message.getExtension(UnittestProto.repeatedBytesExtension, 0));
-
- assertEqualsExactType(217, message.getExtension(UnittestProto.repeatedGroupExtension , 0).getA());
- assertEqualsExactType(218, message.getExtension(UnittestProto.repeatedNestedMessageExtension , 0).getBb());
- assertEqualsExactType(219, message.getExtension(UnittestProto.repeatedForeignMessageExtension, 0).getC());
- assertEqualsExactType(220, message.getExtension(UnittestProto.repeatedImportMessageExtension , 0).getD());
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32Extension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64Extension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtension ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtension ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtension));
+
+ assertEqualsExactType(201 , message.getExtension(repeatedInt32Extension , 0));
+ assertEqualsExactType(202L , message.getExtension(repeatedInt64Extension , 0));
+ assertEqualsExactType(203 , message.getExtension(repeatedUint32Extension , 0));
+ assertEqualsExactType(204L , message.getExtension(repeatedUint64Extension , 0));
+ assertEqualsExactType(205 , message.getExtension(repeatedSint32Extension , 0));
+ assertEqualsExactType(206L , message.getExtension(repeatedSint64Extension , 0));
+ assertEqualsExactType(207 , message.getExtension(repeatedFixed32Extension , 0));
+ assertEqualsExactType(208L , message.getExtension(repeatedFixed64Extension , 0));
+ assertEqualsExactType(209 , message.getExtension(repeatedSfixed32Extension, 0));
+ assertEqualsExactType(210L , message.getExtension(repeatedSfixed64Extension, 0));
+ assertEqualsExactType(211F , message.getExtension(repeatedFloatExtension , 0));
+ assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtension , 0));
+ assertEqualsExactType(true , message.getExtension(repeatedBoolExtension , 0));
+ assertEqualsExactType("215", message.getExtension(repeatedStringExtension , 0));
+ assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtension, 0));
+
+ assertEqualsExactType(217, message.getExtension(repeatedGroupExtension , 0).getA());
+ assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtension , 0).getBb());
+ assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtension, 0).getC());
+ assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtension , 0).getD());
assertEqualsExactType(TestAllTypes.NestedEnum.BAR,
- message.getExtension(UnittestProto.repeatedNestedEnumExtension, 0));
+ message.getExtension(repeatedNestedEnumExtension, 0));
assertEqualsExactType(ForeignEnum.FOREIGN_BAR,
- message.getExtension(UnittestProto.repeatedForeignEnumExtension, 0));
+ message.getExtension(repeatedForeignEnumExtension, 0));
assertEqualsExactType(ImportEnum.IMPORT_BAR,
- message.getExtension(UnittestProto.repeatedImportEnumExtension, 0));
-
- assertEqualsExactType("224", message.getExtension(UnittestProto.repeatedStringPieceExtension, 0));
- assertEqualsExactType("225", message.getExtension(UnittestProto.repeatedCordExtension, 0));
-
- assertEqualsExactType(301 , message.getExtension(UnittestProto.repeatedInt32Extension , 1));
- assertEqualsExactType(302L , message.getExtension(UnittestProto.repeatedInt64Extension , 1));
- assertEqualsExactType(303 , message.getExtension(UnittestProto.repeatedUint32Extension , 1));
- assertEqualsExactType(304L , message.getExtension(UnittestProto.repeatedUint64Extension , 1));
- assertEqualsExactType(305 , message.getExtension(UnittestProto.repeatedSint32Extension , 1));
- assertEqualsExactType(306L , message.getExtension(UnittestProto.repeatedSint64Extension , 1));
- assertEqualsExactType(307 , message.getExtension(UnittestProto.repeatedFixed32Extension , 1));
- assertEqualsExactType(308L , message.getExtension(UnittestProto.repeatedFixed64Extension , 1));
- assertEqualsExactType(309 , message.getExtension(UnittestProto.repeatedSfixed32Extension, 1));
- assertEqualsExactType(310L , message.getExtension(UnittestProto.repeatedSfixed64Extension, 1));
- assertEqualsExactType(311F , message.getExtension(UnittestProto.repeatedFloatExtension , 1));
- assertEqualsExactType(312D , message.getExtension(UnittestProto.repeatedDoubleExtension , 1));
- assertEqualsExactType(false, message.getExtension(UnittestProto.repeatedBoolExtension , 1));
- assertEqualsExactType("315", message.getExtension(UnittestProto.repeatedStringExtension , 1));
- assertEqualsExactType(toBytes("316"), message.getExtension(UnittestProto.repeatedBytesExtension, 1));
-
- assertEqualsExactType(317, message.getExtension(UnittestProto.repeatedGroupExtension , 1).getA());
- assertEqualsExactType(318, message.getExtension(UnittestProto.repeatedNestedMessageExtension , 1).getBb());
- assertEqualsExactType(319, message.getExtension(UnittestProto.repeatedForeignMessageExtension, 1).getC());
- assertEqualsExactType(320, message.getExtension(UnittestProto.repeatedImportMessageExtension , 1).getD());
+ message.getExtension(repeatedImportEnumExtension, 0));
+
+ assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtension, 0));
+ assertEqualsExactType("225", message.getExtension(repeatedCordExtension, 0));
+
+ assertEqualsExactType(301 , message.getExtension(repeatedInt32Extension , 1));
+ assertEqualsExactType(302L , message.getExtension(repeatedInt64Extension , 1));
+ assertEqualsExactType(303 , message.getExtension(repeatedUint32Extension , 1));
+ assertEqualsExactType(304L , message.getExtension(repeatedUint64Extension , 1));
+ assertEqualsExactType(305 , message.getExtension(repeatedSint32Extension , 1));
+ assertEqualsExactType(306L , message.getExtension(repeatedSint64Extension , 1));
+ assertEqualsExactType(307 , message.getExtension(repeatedFixed32Extension , 1));
+ assertEqualsExactType(308L , message.getExtension(repeatedFixed64Extension , 1));
+ assertEqualsExactType(309 , message.getExtension(repeatedSfixed32Extension, 1));
+ assertEqualsExactType(310L , message.getExtension(repeatedSfixed64Extension, 1));
+ assertEqualsExactType(311F , message.getExtension(repeatedFloatExtension , 1));
+ assertEqualsExactType(312D , message.getExtension(repeatedDoubleExtension , 1));
+ assertEqualsExactType(false, message.getExtension(repeatedBoolExtension , 1));
+ assertEqualsExactType("315", message.getExtension(repeatedStringExtension , 1));
+ assertEqualsExactType(toBytes("316"), message.getExtension(repeatedBytesExtension, 1));
+
+ assertEqualsExactType(317, message.getExtension(repeatedGroupExtension , 1).getA());
+ assertEqualsExactType(318, message.getExtension(repeatedNestedMessageExtension , 1).getBb());
+ assertEqualsExactType(319, message.getExtension(repeatedForeignMessageExtension, 1).getC());
+ assertEqualsExactType(320, message.getExtension(repeatedImportMessageExtension , 1).getD());
assertEqualsExactType(TestAllTypes.NestedEnum.BAZ,
- message.getExtension(UnittestProto.repeatedNestedEnumExtension, 1));
+ message.getExtension(repeatedNestedEnumExtension, 1));
assertEqualsExactType(ForeignEnum.FOREIGN_BAZ,
- message.getExtension(UnittestProto.repeatedForeignEnumExtension, 1));
+ message.getExtension(repeatedForeignEnumExtension, 1));
assertEqualsExactType(ImportEnum.IMPORT_BAZ,
- message.getExtension(UnittestProto.repeatedImportEnumExtension, 1));
+ message.getExtension(repeatedImportEnumExtension, 1));
- assertEqualsExactType("324", message.getExtension(UnittestProto.repeatedStringPieceExtension, 1));
- assertEqualsExactType("325", message.getExtension(UnittestProto.repeatedCordExtension, 1));
+ assertEqualsExactType("324", message.getExtension(repeatedStringPieceExtension, 1));
+ assertEqualsExactType("325", message.getExtension(repeatedCordExtension, 1));
// -----------------------------------------------------------------
- Assert.assertTrue(message.hasExtension(UnittestProto.defaultInt32Extension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.defaultInt64Extension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.defaultUint32Extension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.defaultUint64Extension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.defaultSint32Extension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.defaultSint64Extension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.defaultFixed32Extension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.defaultFixed64Extension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.defaultSfixed32Extension));
- Assert.assertTrue(message.hasExtension(UnittestProto.defaultSfixed64Extension));
- Assert.assertTrue(message.hasExtension(UnittestProto.defaultFloatExtension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.defaultDoubleExtension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.defaultBoolExtension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.defaultStringExtension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.defaultBytesExtension ));
-
- Assert.assertTrue(message.hasExtension(UnittestProto.defaultNestedEnumExtension ));
- Assert.assertTrue(message.hasExtension(UnittestProto.defaultForeignEnumExtension));
- Assert.assertTrue(message.hasExtension(UnittestProto.defaultImportEnumExtension ));
-
- Assert.assertTrue(message.hasExtension(UnittestProto.defaultStringPieceExtension));
- Assert.assertTrue(message.hasExtension(UnittestProto.defaultCordExtension));
-
- assertEqualsExactType(401 , message.getExtension(UnittestProto.defaultInt32Extension ));
- assertEqualsExactType(402L , message.getExtension(UnittestProto.defaultInt64Extension ));
- assertEqualsExactType(403 , message.getExtension(UnittestProto.defaultUint32Extension ));
- assertEqualsExactType(404L , message.getExtension(UnittestProto.defaultUint64Extension ));
- assertEqualsExactType(405 , message.getExtension(UnittestProto.defaultSint32Extension ));
- assertEqualsExactType(406L , message.getExtension(UnittestProto.defaultSint64Extension ));
- assertEqualsExactType(407 , message.getExtension(UnittestProto.defaultFixed32Extension ));
- assertEqualsExactType(408L , message.getExtension(UnittestProto.defaultFixed64Extension ));
- assertEqualsExactType(409 , message.getExtension(UnittestProto.defaultSfixed32Extension));
- assertEqualsExactType(410L , message.getExtension(UnittestProto.defaultSfixed64Extension));
- assertEqualsExactType(411F , message.getExtension(UnittestProto.defaultFloatExtension ));
- assertEqualsExactType(412D , message.getExtension(UnittestProto.defaultDoubleExtension ));
- assertEqualsExactType(false, message.getExtension(UnittestProto.defaultBoolExtension ));
- assertEqualsExactType("415", message.getExtension(UnittestProto.defaultStringExtension ));
- assertEqualsExactType(toBytes("416"), message.getExtension(UnittestProto.defaultBytesExtension));
+ Assert.assertTrue(message.hasExtension(defaultInt32Extension ));
+ Assert.assertTrue(message.hasExtension(defaultInt64Extension ));
+ Assert.assertTrue(message.hasExtension(defaultUint32Extension ));
+ Assert.assertTrue(message.hasExtension(defaultUint64Extension ));
+ Assert.assertTrue(message.hasExtension(defaultSint32Extension ));
+ Assert.assertTrue(message.hasExtension(defaultSint64Extension ));
+ Assert.assertTrue(message.hasExtension(defaultFixed32Extension ));
+ Assert.assertTrue(message.hasExtension(defaultFixed64Extension ));
+ Assert.assertTrue(message.hasExtension(defaultSfixed32Extension));
+ Assert.assertTrue(message.hasExtension(defaultSfixed64Extension));
+ Assert.assertTrue(message.hasExtension(defaultFloatExtension ));
+ Assert.assertTrue(message.hasExtension(defaultDoubleExtension ));
+ Assert.assertTrue(message.hasExtension(defaultBoolExtension ));
+ Assert.assertTrue(message.hasExtension(defaultStringExtension ));
+ Assert.assertTrue(message.hasExtension(defaultBytesExtension ));
+
+ Assert.assertTrue(message.hasExtension(defaultNestedEnumExtension ));
+ Assert.assertTrue(message.hasExtension(defaultForeignEnumExtension));
+ Assert.assertTrue(message.hasExtension(defaultImportEnumExtension ));
+
+ Assert.assertTrue(message.hasExtension(defaultStringPieceExtension));
+ Assert.assertTrue(message.hasExtension(defaultCordExtension));
+
+ assertEqualsExactType(401 , message.getExtension(defaultInt32Extension ));
+ assertEqualsExactType(402L , message.getExtension(defaultInt64Extension ));
+ assertEqualsExactType(403 , message.getExtension(defaultUint32Extension ));
+ assertEqualsExactType(404L , message.getExtension(defaultUint64Extension ));
+ assertEqualsExactType(405 , message.getExtension(defaultSint32Extension ));
+ assertEqualsExactType(406L , message.getExtension(defaultSint64Extension ));
+ assertEqualsExactType(407 , message.getExtension(defaultFixed32Extension ));
+ assertEqualsExactType(408L , message.getExtension(defaultFixed64Extension ));
+ assertEqualsExactType(409 , message.getExtension(defaultSfixed32Extension));
+ assertEqualsExactType(410L , message.getExtension(defaultSfixed64Extension));
+ assertEqualsExactType(411F , message.getExtension(defaultFloatExtension ));
+ assertEqualsExactType(412D , message.getExtension(defaultDoubleExtension ));
+ assertEqualsExactType(false, message.getExtension(defaultBoolExtension ));
+ assertEqualsExactType("415", message.getExtension(defaultStringExtension ));
+ assertEqualsExactType(toBytes("416"), message.getExtension(defaultBytesExtension));
assertEqualsExactType(TestAllTypes.NestedEnum.FOO,
- message.getExtension(UnittestProto.defaultNestedEnumExtension ));
+ message.getExtension(defaultNestedEnumExtension ));
assertEqualsExactType(ForeignEnum.FOREIGN_FOO,
- message.getExtension(UnittestProto.defaultForeignEnumExtension));
+ message.getExtension(defaultForeignEnumExtension));
assertEqualsExactType(ImportEnum.IMPORT_FOO,
- message.getExtension(UnittestProto.defaultImportEnumExtension));
+ message.getExtension(defaultImportEnumExtension));
- assertEqualsExactType("424", message.getExtension(UnittestProto.defaultStringPieceExtension));
- assertEqualsExactType("425", message.getExtension(UnittestProto.defaultCordExtension));
+ assertEqualsExactType("424", message.getExtension(defaultStringPieceExtension));
+ assertEqualsExactType("425", message.getExtension(defaultCordExtension));
}
// -------------------------------------------------------------------
@@ -1174,151 +1259,151 @@ class TestUtil {
*/
public static void assertExtensionsClear(TestAllExtensions message) {
// hasBlah() should initially be false for all optional fields.
- Assert.assertFalse(message.hasExtension(UnittestProto.optionalInt32Extension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.optionalInt64Extension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.optionalUint32Extension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.optionalUint64Extension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.optionalSint32Extension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.optionalSint64Extension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.optionalFixed32Extension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.optionalFixed64Extension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.optionalSfixed32Extension));
- Assert.assertFalse(message.hasExtension(UnittestProto.optionalSfixed64Extension));
- Assert.assertFalse(message.hasExtension(UnittestProto.optionalFloatExtension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.optionalDoubleExtension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.optionalBoolExtension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.optionalStringExtension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.optionalBytesExtension ));
-
- Assert.assertFalse(message.hasExtension(UnittestProto.optionalGroupExtension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.optionalNestedMessageExtension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.optionalForeignMessageExtension));
- Assert.assertFalse(message.hasExtension(UnittestProto.optionalImportMessageExtension ));
-
- Assert.assertFalse(message.hasExtension(UnittestProto.optionalNestedEnumExtension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.optionalForeignEnumExtension));
- Assert.assertFalse(message.hasExtension(UnittestProto.optionalImportEnumExtension ));
-
- Assert.assertFalse(message.hasExtension(UnittestProto.optionalStringPieceExtension));
- Assert.assertFalse(message.hasExtension(UnittestProto.optionalCordExtension));
+ Assert.assertFalse(message.hasExtension(optionalInt32Extension ));
+ Assert.assertFalse(message.hasExtension(optionalInt64Extension ));
+ Assert.assertFalse(message.hasExtension(optionalUint32Extension ));
+ Assert.assertFalse(message.hasExtension(optionalUint64Extension ));
+ Assert.assertFalse(message.hasExtension(optionalSint32Extension ));
+ Assert.assertFalse(message.hasExtension(optionalSint64Extension ));
+ Assert.assertFalse(message.hasExtension(optionalFixed32Extension ));
+ Assert.assertFalse(message.hasExtension(optionalFixed64Extension ));
+ Assert.assertFalse(message.hasExtension(optionalSfixed32Extension));
+ Assert.assertFalse(message.hasExtension(optionalSfixed64Extension));
+ Assert.assertFalse(message.hasExtension(optionalFloatExtension ));
+ Assert.assertFalse(message.hasExtension(optionalDoubleExtension ));
+ Assert.assertFalse(message.hasExtension(optionalBoolExtension ));
+ Assert.assertFalse(message.hasExtension(optionalStringExtension ));
+ Assert.assertFalse(message.hasExtension(optionalBytesExtension ));
+
+ Assert.assertFalse(message.hasExtension(optionalGroupExtension ));
+ Assert.assertFalse(message.hasExtension(optionalNestedMessageExtension ));
+ Assert.assertFalse(message.hasExtension(optionalForeignMessageExtension));
+ Assert.assertFalse(message.hasExtension(optionalImportMessageExtension ));
+
+ Assert.assertFalse(message.hasExtension(optionalNestedEnumExtension ));
+ Assert.assertFalse(message.hasExtension(optionalForeignEnumExtension));
+ Assert.assertFalse(message.hasExtension(optionalImportEnumExtension ));
+
+ Assert.assertFalse(message.hasExtension(optionalStringPieceExtension));
+ Assert.assertFalse(message.hasExtension(optionalCordExtension));
// Optional fields without defaults are set to zero or something like it.
- assertEqualsExactType(0 , message.getExtension(UnittestProto.optionalInt32Extension ));
- assertEqualsExactType(0L , message.getExtension(UnittestProto.optionalInt64Extension ));
- assertEqualsExactType(0 , message.getExtension(UnittestProto.optionalUint32Extension ));
- assertEqualsExactType(0L , message.getExtension(UnittestProto.optionalUint64Extension ));
- assertEqualsExactType(0 , message.getExtension(UnittestProto.optionalSint32Extension ));
- assertEqualsExactType(0L , message.getExtension(UnittestProto.optionalSint64Extension ));
- assertEqualsExactType(0 , message.getExtension(UnittestProto.optionalFixed32Extension ));
- assertEqualsExactType(0L , message.getExtension(UnittestProto.optionalFixed64Extension ));
- assertEqualsExactType(0 , message.getExtension(UnittestProto.optionalSfixed32Extension));
- assertEqualsExactType(0L , message.getExtension(UnittestProto.optionalSfixed64Extension));
- assertEqualsExactType(0F , message.getExtension(UnittestProto.optionalFloatExtension ));
- assertEqualsExactType(0D , message.getExtension(UnittestProto.optionalDoubleExtension ));
- assertEqualsExactType(false, message.getExtension(UnittestProto.optionalBoolExtension ));
- assertEqualsExactType("" , message.getExtension(UnittestProto.optionalStringExtension ));
- assertEqualsExactType(ByteString.EMPTY, message.getExtension(UnittestProto.optionalBytesExtension));
+ assertEqualsExactType(0 , message.getExtension(optionalInt32Extension ));
+ assertEqualsExactType(0L , message.getExtension(optionalInt64Extension ));
+ assertEqualsExactType(0 , message.getExtension(optionalUint32Extension ));
+ assertEqualsExactType(0L , message.getExtension(optionalUint64Extension ));
+ assertEqualsExactType(0 , message.getExtension(optionalSint32Extension ));
+ assertEqualsExactType(0L , message.getExtension(optionalSint64Extension ));
+ assertEqualsExactType(0 , message.getExtension(optionalFixed32Extension ));
+ assertEqualsExactType(0L , message.getExtension(optionalFixed64Extension ));
+ assertEqualsExactType(0 , message.getExtension(optionalSfixed32Extension));
+ assertEqualsExactType(0L , message.getExtension(optionalSfixed64Extension));
+ assertEqualsExactType(0F , message.getExtension(optionalFloatExtension ));
+ assertEqualsExactType(0D , message.getExtension(optionalDoubleExtension ));
+ assertEqualsExactType(false, message.getExtension(optionalBoolExtension ));
+ assertEqualsExactType("" , message.getExtension(optionalStringExtension ));
+ assertEqualsExactType(ByteString.EMPTY, message.getExtension(optionalBytesExtension));
// Embedded messages should also be clear.
- Assert.assertFalse(message.getExtension(UnittestProto.optionalGroupExtension ).hasA());
- Assert.assertFalse(message.getExtension(UnittestProto.optionalNestedMessageExtension ).hasBb());
- Assert.assertFalse(message.getExtension(UnittestProto.optionalForeignMessageExtension).hasC());
- Assert.assertFalse(message.getExtension(UnittestProto.optionalImportMessageExtension ).hasD());
+ Assert.assertFalse(message.getExtension(optionalGroupExtension ).hasA());
+ Assert.assertFalse(message.getExtension(optionalNestedMessageExtension ).hasBb());
+ Assert.assertFalse(message.getExtension(optionalForeignMessageExtension).hasC());
+ Assert.assertFalse(message.getExtension(optionalImportMessageExtension ).hasD());
- assertEqualsExactType(0, message.getExtension(UnittestProto.optionalGroupExtension ).getA());
- assertEqualsExactType(0, message.getExtension(UnittestProto.optionalNestedMessageExtension ).getBb());
- assertEqualsExactType(0, message.getExtension(UnittestProto.optionalForeignMessageExtension).getC());
- assertEqualsExactType(0, message.getExtension(UnittestProto.optionalImportMessageExtension ).getD());
+ assertEqualsExactType(0, message.getExtension(optionalGroupExtension ).getA());
+ assertEqualsExactType(0, message.getExtension(optionalNestedMessageExtension ).getBb());
+ assertEqualsExactType(0, message.getExtension(optionalForeignMessageExtension).getC());
+ assertEqualsExactType(0, message.getExtension(optionalImportMessageExtension ).getD());
// Enums without defaults are set to the first value in the enum.
assertEqualsExactType(TestAllTypes.NestedEnum.FOO,
- message.getExtension(UnittestProto.optionalNestedEnumExtension ));
+ message.getExtension(optionalNestedEnumExtension ));
assertEqualsExactType(ForeignEnum.FOREIGN_FOO,
- message.getExtension(UnittestProto.optionalForeignEnumExtension));
+ message.getExtension(optionalForeignEnumExtension));
assertEqualsExactType(ImportEnum.IMPORT_FOO,
- message.getExtension(UnittestProto.optionalImportEnumExtension));
+ message.getExtension(optionalImportEnumExtension));
- assertEqualsExactType("", message.getExtension(UnittestProto.optionalStringPieceExtension));
- assertEqualsExactType("", message.getExtension(UnittestProto.optionalCordExtension));
+ assertEqualsExactType("", message.getExtension(optionalStringPieceExtension));
+ assertEqualsExactType("", message.getExtension(optionalCordExtension));
// Repeated fields are empty.
- Assert.assertEquals(0, message.getExtensionCount(UnittestProto.repeatedInt32Extension ));
- Assert.assertEquals(0, message.getExtensionCount(UnittestProto.repeatedInt64Extension ));
- Assert.assertEquals(0, message.getExtensionCount(UnittestProto.repeatedUint32Extension ));
- Assert.assertEquals(0, message.getExtensionCount(UnittestProto.repeatedUint64Extension ));
- Assert.assertEquals(0, message.getExtensionCount(UnittestProto.repeatedSint32Extension ));
- Assert.assertEquals(0, message.getExtensionCount(UnittestProto.repeatedSint64Extension ));
- Assert.assertEquals(0, message.getExtensionCount(UnittestProto.repeatedFixed32Extension ));
- Assert.assertEquals(0, message.getExtensionCount(UnittestProto.repeatedFixed64Extension ));
- Assert.assertEquals(0, message.getExtensionCount(UnittestProto.repeatedSfixed32Extension));
- Assert.assertEquals(0, message.getExtensionCount(UnittestProto.repeatedSfixed64Extension));
- Assert.assertEquals(0, message.getExtensionCount(UnittestProto.repeatedFloatExtension ));
- Assert.assertEquals(0, message.getExtensionCount(UnittestProto.repeatedDoubleExtension ));
- Assert.assertEquals(0, message.getExtensionCount(UnittestProto.repeatedBoolExtension ));
- Assert.assertEquals(0, message.getExtensionCount(UnittestProto.repeatedStringExtension ));
- Assert.assertEquals(0, message.getExtensionCount(UnittestProto.repeatedBytesExtension ));
-
- Assert.assertEquals(0, message.getExtensionCount(UnittestProto.repeatedGroupExtension ));
- Assert.assertEquals(0, message.getExtensionCount(UnittestProto.repeatedNestedMessageExtension ));
- Assert.assertEquals(0, message.getExtensionCount(UnittestProto.repeatedForeignMessageExtension));
- Assert.assertEquals(0, message.getExtensionCount(UnittestProto.repeatedImportMessageExtension ));
- Assert.assertEquals(0, message.getExtensionCount(UnittestProto.repeatedNestedEnumExtension ));
- Assert.assertEquals(0, message.getExtensionCount(UnittestProto.repeatedForeignEnumExtension ));
- Assert.assertEquals(0, message.getExtensionCount(UnittestProto.repeatedImportEnumExtension ));
-
- Assert.assertEquals(0, message.getExtensionCount(UnittestProto.repeatedStringPieceExtension));
- Assert.assertEquals(0, message.getExtensionCount(UnittestProto.repeatedCordExtension));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedInt32Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedInt64Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedUint32Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedUint64Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSint32Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSint64Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedFixed32Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedFixed64Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed32Extension));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed64Extension));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedFloatExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedDoubleExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedBoolExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedStringExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedBytesExtension ));
+
+ Assert.assertEquals(0, message.getExtensionCount(repeatedGroupExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedNestedMessageExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedForeignMessageExtension));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedImportMessageExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedNestedEnumExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedForeignEnumExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedImportEnumExtension ));
+
+ Assert.assertEquals(0, message.getExtensionCount(repeatedStringPieceExtension));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedCordExtension));
// hasBlah() should also be false for all default fields.
- Assert.assertFalse(message.hasExtension(UnittestProto.defaultInt32Extension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.defaultInt64Extension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.defaultUint32Extension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.defaultUint64Extension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.defaultSint32Extension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.defaultSint64Extension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.defaultFixed32Extension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.defaultFixed64Extension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.defaultSfixed32Extension));
- Assert.assertFalse(message.hasExtension(UnittestProto.defaultSfixed64Extension));
- Assert.assertFalse(message.hasExtension(UnittestProto.defaultFloatExtension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.defaultDoubleExtension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.defaultBoolExtension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.defaultStringExtension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.defaultBytesExtension ));
-
- Assert.assertFalse(message.hasExtension(UnittestProto.defaultNestedEnumExtension ));
- Assert.assertFalse(message.hasExtension(UnittestProto.defaultForeignEnumExtension));
- Assert.assertFalse(message.hasExtension(UnittestProto.defaultImportEnumExtension ));
-
- Assert.assertFalse(message.hasExtension(UnittestProto.defaultStringPieceExtension));
- Assert.assertFalse(message.hasExtension(UnittestProto.defaultCordExtension));
+ Assert.assertFalse(message.hasExtension(defaultInt32Extension ));
+ Assert.assertFalse(message.hasExtension(defaultInt64Extension ));
+ Assert.assertFalse(message.hasExtension(defaultUint32Extension ));
+ Assert.assertFalse(message.hasExtension(defaultUint64Extension ));
+ Assert.assertFalse(message.hasExtension(defaultSint32Extension ));
+ Assert.assertFalse(message.hasExtension(defaultSint64Extension ));
+ Assert.assertFalse(message.hasExtension(defaultFixed32Extension ));
+ Assert.assertFalse(message.hasExtension(defaultFixed64Extension ));
+ Assert.assertFalse(message.hasExtension(defaultSfixed32Extension));
+ Assert.assertFalse(message.hasExtension(defaultSfixed64Extension));
+ Assert.assertFalse(message.hasExtension(defaultFloatExtension ));
+ Assert.assertFalse(message.hasExtension(defaultDoubleExtension ));
+ Assert.assertFalse(message.hasExtension(defaultBoolExtension ));
+ Assert.assertFalse(message.hasExtension(defaultStringExtension ));
+ Assert.assertFalse(message.hasExtension(defaultBytesExtension ));
+
+ Assert.assertFalse(message.hasExtension(defaultNestedEnumExtension ));
+ Assert.assertFalse(message.hasExtension(defaultForeignEnumExtension));
+ Assert.assertFalse(message.hasExtension(defaultImportEnumExtension ));
+
+ Assert.assertFalse(message.hasExtension(defaultStringPieceExtension));
+ Assert.assertFalse(message.hasExtension(defaultCordExtension));
// Fields with defaults have their default values (duh).
- assertEqualsExactType( 41 , message.getExtension(UnittestProto.defaultInt32Extension ));
- assertEqualsExactType( 42L , message.getExtension(UnittestProto.defaultInt64Extension ));
- assertEqualsExactType( 43 , message.getExtension(UnittestProto.defaultUint32Extension ));
- assertEqualsExactType( 44L , message.getExtension(UnittestProto.defaultUint64Extension ));
- assertEqualsExactType(-45 , message.getExtension(UnittestProto.defaultSint32Extension ));
- assertEqualsExactType( 46L , message.getExtension(UnittestProto.defaultSint64Extension ));
- assertEqualsExactType( 47 , message.getExtension(UnittestProto.defaultFixed32Extension ));
- assertEqualsExactType( 48L , message.getExtension(UnittestProto.defaultFixed64Extension ));
- assertEqualsExactType( 49 , message.getExtension(UnittestProto.defaultSfixed32Extension));
- assertEqualsExactType(-50L , message.getExtension(UnittestProto.defaultSfixed64Extension));
- assertEqualsExactType( 51.5F , message.getExtension(UnittestProto.defaultFloatExtension ));
- assertEqualsExactType( 52e3D , message.getExtension(UnittestProto.defaultDoubleExtension ));
- assertEqualsExactType(true , message.getExtension(UnittestProto.defaultBoolExtension ));
- assertEqualsExactType("hello", message.getExtension(UnittestProto.defaultStringExtension ));
- assertEqualsExactType(toBytes("world"), message.getExtension(UnittestProto.defaultBytesExtension));
+ assertEqualsExactType( 41 , message.getExtension(defaultInt32Extension ));
+ assertEqualsExactType( 42L , message.getExtension(defaultInt64Extension ));
+ assertEqualsExactType( 43 , message.getExtension(defaultUint32Extension ));
+ assertEqualsExactType( 44L , message.getExtension(defaultUint64Extension ));
+ assertEqualsExactType(-45 , message.getExtension(defaultSint32Extension ));
+ assertEqualsExactType( 46L , message.getExtension(defaultSint64Extension ));
+ assertEqualsExactType( 47 , message.getExtension(defaultFixed32Extension ));
+ assertEqualsExactType( 48L , message.getExtension(defaultFixed64Extension ));
+ assertEqualsExactType( 49 , message.getExtension(defaultSfixed32Extension));
+ assertEqualsExactType(-50L , message.getExtension(defaultSfixed64Extension));
+ assertEqualsExactType( 51.5F , message.getExtension(defaultFloatExtension ));
+ assertEqualsExactType( 52e3D , message.getExtension(defaultDoubleExtension ));
+ assertEqualsExactType(true , message.getExtension(defaultBoolExtension ));
+ assertEqualsExactType("hello", message.getExtension(defaultStringExtension ));
+ assertEqualsExactType(toBytes("world"), message.getExtension(defaultBytesExtension));
assertEqualsExactType(TestAllTypes.NestedEnum.BAR,
- message.getExtension(UnittestProto.defaultNestedEnumExtension ));
+ message.getExtension(defaultNestedEnumExtension ));
assertEqualsExactType(ForeignEnum.FOREIGN_BAR,
- message.getExtension(UnittestProto.defaultForeignEnumExtension));
+ message.getExtension(defaultForeignEnumExtension));
assertEqualsExactType(ImportEnum.IMPORT_BAR,
- message.getExtension(UnittestProto.defaultImportEnumExtension));
+ message.getExtension(defaultImportEnumExtension));
- assertEqualsExactType("abc", message.getExtension(UnittestProto.defaultStringPieceExtension));
- assertEqualsExactType("123", message.getExtension(UnittestProto.defaultCordExtension));
+ assertEqualsExactType("abc", message.getExtension(defaultStringPieceExtension));
+ assertEqualsExactType("123", message.getExtension(defaultCordExtension));
}
// -------------------------------------------------------------------
@@ -1333,97 +1418,261 @@ class TestUtil {
// ModifyRepeatedFields only sets the second repeated element of each
// field. In addition to verifying this, we also verify that the first
// element and size were *not* modified.
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedInt32Extension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedInt64Extension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedUint32Extension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedUint64Extension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedSint32Extension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedSint64Extension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedFixed32Extension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedFixed64Extension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedSfixed32Extension));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedSfixed64Extension));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedFloatExtension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedDoubleExtension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedBoolExtension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedStringExtension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedBytesExtension ));
-
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedGroupExtension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedNestedMessageExtension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedForeignMessageExtension));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedImportMessageExtension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedNestedEnumExtension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedForeignEnumExtension ));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedImportEnumExtension ));
-
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedStringPieceExtension));
- Assert.assertEquals(2, message.getExtensionCount(UnittestProto.repeatedCordExtension));
-
- assertEqualsExactType(201 , message.getExtension(UnittestProto.repeatedInt32Extension , 0));
- assertEqualsExactType(202L , message.getExtension(UnittestProto.repeatedInt64Extension , 0));
- assertEqualsExactType(203 , message.getExtension(UnittestProto.repeatedUint32Extension , 0));
- assertEqualsExactType(204L , message.getExtension(UnittestProto.repeatedUint64Extension , 0));
- assertEqualsExactType(205 , message.getExtension(UnittestProto.repeatedSint32Extension , 0));
- assertEqualsExactType(206L , message.getExtension(UnittestProto.repeatedSint64Extension , 0));
- assertEqualsExactType(207 , message.getExtension(UnittestProto.repeatedFixed32Extension , 0));
- assertEqualsExactType(208L , message.getExtension(UnittestProto.repeatedFixed64Extension , 0));
- assertEqualsExactType(209 , message.getExtension(UnittestProto.repeatedSfixed32Extension, 0));
- assertEqualsExactType(210L , message.getExtension(UnittestProto.repeatedSfixed64Extension, 0));
- assertEqualsExactType(211F , message.getExtension(UnittestProto.repeatedFloatExtension , 0));
- assertEqualsExactType(212D , message.getExtension(UnittestProto.repeatedDoubleExtension , 0));
- assertEqualsExactType(true , message.getExtension(UnittestProto.repeatedBoolExtension , 0));
- assertEqualsExactType("215", message.getExtension(UnittestProto.repeatedStringExtension , 0));
- assertEqualsExactType(toBytes("216"), message.getExtension(UnittestProto.repeatedBytesExtension, 0));
-
- assertEqualsExactType(217, message.getExtension(UnittestProto.repeatedGroupExtension , 0).getA());
- assertEqualsExactType(218, message.getExtension(UnittestProto.repeatedNestedMessageExtension , 0).getBb());
- assertEqualsExactType(219, message.getExtension(UnittestProto.repeatedForeignMessageExtension, 0).getC());
- assertEqualsExactType(220, message.getExtension(UnittestProto.repeatedImportMessageExtension , 0).getD());
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32Extension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64Extension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtension ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtension ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtension));
+
+ assertEqualsExactType(201 , message.getExtension(repeatedInt32Extension , 0));
+ assertEqualsExactType(202L , message.getExtension(repeatedInt64Extension , 0));
+ assertEqualsExactType(203 , message.getExtension(repeatedUint32Extension , 0));
+ assertEqualsExactType(204L , message.getExtension(repeatedUint64Extension , 0));
+ assertEqualsExactType(205 , message.getExtension(repeatedSint32Extension , 0));
+ assertEqualsExactType(206L , message.getExtension(repeatedSint64Extension , 0));
+ assertEqualsExactType(207 , message.getExtension(repeatedFixed32Extension , 0));
+ assertEqualsExactType(208L , message.getExtension(repeatedFixed64Extension , 0));
+ assertEqualsExactType(209 , message.getExtension(repeatedSfixed32Extension, 0));
+ assertEqualsExactType(210L , message.getExtension(repeatedSfixed64Extension, 0));
+ assertEqualsExactType(211F , message.getExtension(repeatedFloatExtension , 0));
+ assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtension , 0));
+ assertEqualsExactType(true , message.getExtension(repeatedBoolExtension , 0));
+ assertEqualsExactType("215", message.getExtension(repeatedStringExtension , 0));
+ assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtension, 0));
+
+ assertEqualsExactType(217, message.getExtension(repeatedGroupExtension , 0).getA());
+ assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtension , 0).getBb());
+ assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtension, 0).getC());
+ assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtension , 0).getD());
assertEqualsExactType(TestAllTypes.NestedEnum.BAR,
- message.getExtension(UnittestProto.repeatedNestedEnumExtension, 0));
+ message.getExtension(repeatedNestedEnumExtension, 0));
assertEqualsExactType(ForeignEnum.FOREIGN_BAR,
- message.getExtension(UnittestProto.repeatedForeignEnumExtension, 0));
+ message.getExtension(repeatedForeignEnumExtension, 0));
assertEqualsExactType(ImportEnum.IMPORT_BAR,
- message.getExtension(UnittestProto.repeatedImportEnumExtension, 0));
+ message.getExtension(repeatedImportEnumExtension, 0));
- assertEqualsExactType("224", message.getExtension(UnittestProto.repeatedStringPieceExtension, 0));
- assertEqualsExactType("225", message.getExtension(UnittestProto.repeatedCordExtension, 0));
+ assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtension, 0));
+ assertEqualsExactType("225", message.getExtension(repeatedCordExtension, 0));
// Actually verify the second (modified) elements now.
- assertEqualsExactType(501 , message.getExtension(UnittestProto.repeatedInt32Extension , 1));
- assertEqualsExactType(502L , message.getExtension(UnittestProto.repeatedInt64Extension , 1));
- assertEqualsExactType(503 , message.getExtension(UnittestProto.repeatedUint32Extension , 1));
- assertEqualsExactType(504L , message.getExtension(UnittestProto.repeatedUint64Extension , 1));
- assertEqualsExactType(505 , message.getExtension(UnittestProto.repeatedSint32Extension , 1));
- assertEqualsExactType(506L , message.getExtension(UnittestProto.repeatedSint64Extension , 1));
- assertEqualsExactType(507 , message.getExtension(UnittestProto.repeatedFixed32Extension , 1));
- assertEqualsExactType(508L , message.getExtension(UnittestProto.repeatedFixed64Extension , 1));
- assertEqualsExactType(509 , message.getExtension(UnittestProto.repeatedSfixed32Extension, 1));
- assertEqualsExactType(510L , message.getExtension(UnittestProto.repeatedSfixed64Extension, 1));
- assertEqualsExactType(511F , message.getExtension(UnittestProto.repeatedFloatExtension , 1));
- assertEqualsExactType(512D , message.getExtension(UnittestProto.repeatedDoubleExtension , 1));
- assertEqualsExactType(true , message.getExtension(UnittestProto.repeatedBoolExtension , 1));
- assertEqualsExactType("515", message.getExtension(UnittestProto.repeatedStringExtension , 1));
- assertEqualsExactType(toBytes("516"), message.getExtension(UnittestProto.repeatedBytesExtension, 1));
-
- assertEqualsExactType(517, message.getExtension(UnittestProto.repeatedGroupExtension , 1).getA());
- assertEqualsExactType(518, message.getExtension(UnittestProto.repeatedNestedMessageExtension , 1).getBb());
- assertEqualsExactType(519, message.getExtension(UnittestProto.repeatedForeignMessageExtension, 1).getC());
- assertEqualsExactType(520, message.getExtension(UnittestProto.repeatedImportMessageExtension , 1).getD());
+ assertEqualsExactType(501 , message.getExtension(repeatedInt32Extension , 1));
+ assertEqualsExactType(502L , message.getExtension(repeatedInt64Extension , 1));
+ assertEqualsExactType(503 , message.getExtension(repeatedUint32Extension , 1));
+ assertEqualsExactType(504L , message.getExtension(repeatedUint64Extension , 1));
+ assertEqualsExactType(505 , message.getExtension(repeatedSint32Extension , 1));
+ assertEqualsExactType(506L , message.getExtension(repeatedSint64Extension , 1));
+ assertEqualsExactType(507 , message.getExtension(repeatedFixed32Extension , 1));
+ assertEqualsExactType(508L , message.getExtension(repeatedFixed64Extension , 1));
+ assertEqualsExactType(509 , message.getExtension(repeatedSfixed32Extension, 1));
+ assertEqualsExactType(510L , message.getExtension(repeatedSfixed64Extension, 1));
+ assertEqualsExactType(511F , message.getExtension(repeatedFloatExtension , 1));
+ assertEqualsExactType(512D , message.getExtension(repeatedDoubleExtension , 1));
+ assertEqualsExactType(true , message.getExtension(repeatedBoolExtension , 1));
+ assertEqualsExactType("515", message.getExtension(repeatedStringExtension , 1));
+ assertEqualsExactType(toBytes("516"), message.getExtension(repeatedBytesExtension, 1));
+
+ assertEqualsExactType(517, message.getExtension(repeatedGroupExtension , 1).getA());
+ assertEqualsExactType(518, message.getExtension(repeatedNestedMessageExtension , 1).getBb());
+ assertEqualsExactType(519, message.getExtension(repeatedForeignMessageExtension, 1).getC());
+ assertEqualsExactType(520, message.getExtension(repeatedImportMessageExtension , 1).getD());
assertEqualsExactType(TestAllTypes.NestedEnum.FOO,
- message.getExtension(UnittestProto.repeatedNestedEnumExtension, 1));
+ message.getExtension(repeatedNestedEnumExtension, 1));
assertEqualsExactType(ForeignEnum.FOREIGN_FOO,
- message.getExtension(UnittestProto.repeatedForeignEnumExtension, 1));
+ message.getExtension(repeatedForeignEnumExtension, 1));
assertEqualsExactType(ImportEnum.IMPORT_FOO,
- message.getExtension(UnittestProto.repeatedImportEnumExtension, 1));
+ message.getExtension(repeatedImportEnumExtension, 1));
+
+ assertEqualsExactType("524", message.getExtension(repeatedStringPieceExtension, 1));
+ assertEqualsExactType("525", message.getExtension(repeatedCordExtension, 1));
+ }
- assertEqualsExactType("524", message.getExtension(UnittestProto.repeatedStringPieceExtension, 1));
- assertEqualsExactType("525", message.getExtension(UnittestProto.repeatedCordExtension, 1));
+ /**
+ * Set every field of {@code message} to a unique value.
+ */
+ public static void setPackedFields(TestPackedTypes.Builder message) {
+ message.addPackedInt32 (601);
+ message.addPackedInt64 (602);
+ message.addPackedUint32 (603);
+ message.addPackedUint64 (604);
+ message.addPackedSint32 (605);
+ message.addPackedSint64 (606);
+ message.addPackedFixed32 (607);
+ message.addPackedFixed64 (608);
+ message.addPackedSfixed32(609);
+ message.addPackedSfixed64(610);
+ message.addPackedFloat (611);
+ message.addPackedDouble (612);
+ message.addPackedBool (true);
+ message.addPackedEnum (ForeignEnum.FOREIGN_BAR);
+ // Add a second one of each field.
+ message.addPackedInt32 (701);
+ message.addPackedInt64 (702);
+ message.addPackedUint32 (703);
+ message.addPackedUint64 (704);
+ message.addPackedSint32 (705);
+ message.addPackedSint64 (706);
+ message.addPackedFixed32 (707);
+ message.addPackedFixed64 (708);
+ message.addPackedSfixed32(709);
+ message.addPackedSfixed64(710);
+ message.addPackedFloat (711);
+ message.addPackedDouble (712);
+ message.addPackedBool (false);
+ message.addPackedEnum (ForeignEnum.FOREIGN_BAZ);
}
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all fields of
+ * {@code message} are set to the values assigned by {@code setPackedFields}.
+ */
+ public static void assertPackedFieldsSet(TestPackedTypes message) {
+ Assert.assertEquals(2, message.getPackedInt32Count ());
+ Assert.assertEquals(2, message.getPackedInt64Count ());
+ Assert.assertEquals(2, message.getPackedUint32Count ());
+ Assert.assertEquals(2, message.getPackedUint64Count ());
+ Assert.assertEquals(2, message.getPackedSint32Count ());
+ Assert.assertEquals(2, message.getPackedSint64Count ());
+ Assert.assertEquals(2, message.getPackedFixed32Count ());
+ Assert.assertEquals(2, message.getPackedFixed64Count ());
+ Assert.assertEquals(2, message.getPackedSfixed32Count());
+ Assert.assertEquals(2, message.getPackedSfixed64Count());
+ Assert.assertEquals(2, message.getPackedFloatCount ());
+ Assert.assertEquals(2, message.getPackedDoubleCount ());
+ Assert.assertEquals(2, message.getPackedBoolCount ());
+ Assert.assertEquals(2, message.getPackedEnumCount ());
+ Assert.assertEquals(601 , message.getPackedInt32 (0));
+ Assert.assertEquals(602 , message.getPackedInt64 (0));
+ Assert.assertEquals(603 , message.getPackedUint32 (0));
+ Assert.assertEquals(604 , message.getPackedUint64 (0));
+ Assert.assertEquals(605 , message.getPackedSint32 (0));
+ Assert.assertEquals(606 , message.getPackedSint64 (0));
+ Assert.assertEquals(607 , message.getPackedFixed32 (0));
+ Assert.assertEquals(608 , message.getPackedFixed64 (0));
+ Assert.assertEquals(609 , message.getPackedSfixed32(0));
+ Assert.assertEquals(610 , message.getPackedSfixed64(0));
+ Assert.assertEquals(611 , message.getPackedFloat (0), 0.0);
+ Assert.assertEquals(612 , message.getPackedDouble (0), 0.0);
+ Assert.assertEquals(true , message.getPackedBool (0));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getPackedEnum(0));
+ Assert.assertEquals(701 , message.getPackedInt32 (1));
+ Assert.assertEquals(702 , message.getPackedInt64 (1));
+ Assert.assertEquals(703 , message.getPackedUint32 (1));
+ Assert.assertEquals(704 , message.getPackedUint64 (1));
+ Assert.assertEquals(705 , message.getPackedSint32 (1));
+ Assert.assertEquals(706 , message.getPackedSint64 (1));
+ Assert.assertEquals(707 , message.getPackedFixed32 (1));
+ Assert.assertEquals(708 , message.getPackedFixed64 (1));
+ Assert.assertEquals(709 , message.getPackedSfixed32(1));
+ Assert.assertEquals(710 , message.getPackedSfixed64(1));
+ Assert.assertEquals(711 , message.getPackedFloat (1), 0.0);
+ Assert.assertEquals(712 , message.getPackedDouble (1), 0.0);
+ Assert.assertEquals(false, message.getPackedBool (1));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getPackedEnum(1));
+ }
+
+ public static void setPackedExtensions(TestPackedExtensions.Builder message) {
+ message.addExtension(packedInt32Extension , 601);
+ message.addExtension(packedInt64Extension , 602L);
+ message.addExtension(packedUint32Extension , 603);
+ message.addExtension(packedUint64Extension , 604L);
+ message.addExtension(packedSint32Extension , 605);
+ message.addExtension(packedSint64Extension , 606L);
+ message.addExtension(packedFixed32Extension , 607);
+ message.addExtension(packedFixed64Extension , 608L);
+ message.addExtension(packedSfixed32Extension, 609);
+ message.addExtension(packedSfixed64Extension, 610L);
+ message.addExtension(packedFloatExtension , 611F);
+ message.addExtension(packedDoubleExtension , 612D);
+ message.addExtension(packedBoolExtension , true);
+ message.addExtension(packedEnumExtension, ForeignEnum.FOREIGN_BAR);
+ // Add a second one of each field.
+ message.addExtension(packedInt32Extension , 701);
+ message.addExtension(packedInt64Extension , 702L);
+ message.addExtension(packedUint32Extension , 703);
+ message.addExtension(packedUint64Extension , 704L);
+ message.addExtension(packedSint32Extension , 705);
+ message.addExtension(packedSint64Extension , 706L);
+ message.addExtension(packedFixed32Extension , 707);
+ message.addExtension(packedFixed64Extension , 708L);
+ message.addExtension(packedSfixed32Extension, 709);
+ message.addExtension(packedSfixed64Extension, 710L);
+ message.addExtension(packedFloatExtension , 711F);
+ message.addExtension(packedDoubleExtension , 712D);
+ message.addExtension(packedBoolExtension , false);
+ message.addExtension(packedEnumExtension, ForeignEnum.FOREIGN_BAZ);
+ }
+
+ public static void assertPackedExtensionsSet(TestPackedExtensions message) {
+ Assert.assertEquals(2, message.getExtensionCount(packedInt32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedInt64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedUint32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedUint64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedSint32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedSint64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedFixed32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedFixed64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedSfixed32Extension));
+ Assert.assertEquals(2, message.getExtensionCount(packedSfixed64Extension));
+ Assert.assertEquals(2, message.getExtensionCount(packedFloatExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedDoubleExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedBoolExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedEnumExtension));
+ assertEqualsExactType(601 , message.getExtension(packedInt32Extension , 0));
+ assertEqualsExactType(602L , message.getExtension(packedInt64Extension , 0));
+ assertEqualsExactType(603 , message.getExtension(packedUint32Extension , 0));
+ assertEqualsExactType(604L , message.getExtension(packedUint64Extension , 0));
+ assertEqualsExactType(605 , message.getExtension(packedSint32Extension , 0));
+ assertEqualsExactType(606L , message.getExtension(packedSint64Extension , 0));
+ assertEqualsExactType(607 , message.getExtension(packedFixed32Extension , 0));
+ assertEqualsExactType(608L , message.getExtension(packedFixed64Extension , 0));
+ assertEqualsExactType(609 , message.getExtension(packedSfixed32Extension, 0));
+ assertEqualsExactType(610L , message.getExtension(packedSfixed64Extension, 0));
+ assertEqualsExactType(611F , message.getExtension(packedFloatExtension , 0));
+ assertEqualsExactType(612D , message.getExtension(packedDoubleExtension , 0));
+ assertEqualsExactType(true , message.getExtension(packedBoolExtension , 0));
+ assertEqualsExactType(ForeignEnum.FOREIGN_BAR,
+ message.getExtension(packedEnumExtension, 0));
+ assertEqualsExactType(701 , message.getExtension(packedInt32Extension , 1));
+ assertEqualsExactType(702L , message.getExtension(packedInt64Extension , 1));
+ assertEqualsExactType(703 , message.getExtension(packedUint32Extension , 1));
+ assertEqualsExactType(704L , message.getExtension(packedUint64Extension , 1));
+ assertEqualsExactType(705 , message.getExtension(packedSint32Extension , 1));
+ assertEqualsExactType(706L , message.getExtension(packedSint64Extension , 1));
+ assertEqualsExactType(707 , message.getExtension(packedFixed32Extension , 1));
+ assertEqualsExactType(708L , message.getExtension(packedFixed64Extension , 1));
+ assertEqualsExactType(709 , message.getExtension(packedSfixed32Extension, 1));
+ assertEqualsExactType(710L , message.getExtension(packedSfixed64Extension, 1));
+ assertEqualsExactType(711F , message.getExtension(packedFloatExtension , 1));
+ assertEqualsExactType(712D , message.getExtension(packedDoubleExtension , 1));
+ assertEqualsExactType(false, message.getExtension(packedBoolExtension , 1));
+ assertEqualsExactType(ForeignEnum.FOREIGN_BAZ,
+ message.getExtension(packedEnumExtension, 1));
+ }
+
+
// ===================================================================
/**
@@ -1487,7 +1736,7 @@ class TestUtil {
this.importFile = file.getDependencies().get(0);
Descriptors.Descriptor testAllTypes;
- if (extensionRegistry == null) {
+ if (baseDescriptor.getName() == "TestAllTypes") {
testAllTypes = baseDescriptor;
} else {
testAllTypes = file.findMessageTypeByName("TestAllTypes");
@@ -1495,10 +1744,13 @@ class TestUtil {
}
if (extensionRegistry == null) {
+ // Use testAllTypes, rather than baseDescriptor, to allow
+ // initialization using TestPackedTypes descriptors. These objects
+ // won't be used by the methods for packed fields.
this.optionalGroup =
- baseDescriptor.findNestedTypeByName("OptionalGroup");
+ testAllTypes.findNestedTypeByName("OptionalGroup");
this.repeatedGroup =
- baseDescriptor.findNestedTypeByName("RepeatedGroup");
+ testAllTypes.findNestedTypeByName("RepeatedGroup");
} else {
this.optionalGroup =
file.findMessageTypeByName("OptionalGroup_extension");
@@ -2279,6 +2531,191 @@ class TestUtil {
Assert.assertEquals("524", message.getRepeatedField(f("repeated_string_piece"), 1));
Assert.assertEquals("525", message.getRepeatedField(f("repeated_cord"), 1));
}
+
+ public void setPackedFieldsViaReflection(Message.Builder message) {
+ message.addRepeatedField(f("packed_int32" ), 601 );
+ message.addRepeatedField(f("packed_int64" ), 602L);
+ message.addRepeatedField(f("packed_uint32" ), 603 );
+ message.addRepeatedField(f("packed_uint64" ), 604L);
+ message.addRepeatedField(f("packed_sint32" ), 605 );
+ message.addRepeatedField(f("packed_sint64" ), 606L);
+ message.addRepeatedField(f("packed_fixed32" ), 607 );
+ message.addRepeatedField(f("packed_fixed64" ), 608L);
+ message.addRepeatedField(f("packed_sfixed32"), 609 );
+ message.addRepeatedField(f("packed_sfixed64"), 610L);
+ message.addRepeatedField(f("packed_float" ), 611F);
+ message.addRepeatedField(f("packed_double" ), 612D);
+ message.addRepeatedField(f("packed_bool" ), true);
+ message.addRepeatedField(f("packed_enum" ), foreignBar);
+ // Add a second one of each field.
+ message.addRepeatedField(f("packed_int32" ), 701 );
+ message.addRepeatedField(f("packed_int64" ), 702L);
+ message.addRepeatedField(f("packed_uint32" ), 703 );
+ message.addRepeatedField(f("packed_uint64" ), 704L);
+ message.addRepeatedField(f("packed_sint32" ), 705 );
+ message.addRepeatedField(f("packed_sint64" ), 706L);
+ message.addRepeatedField(f("packed_fixed32" ), 707 );
+ message.addRepeatedField(f("packed_fixed64" ), 708L);
+ message.addRepeatedField(f("packed_sfixed32"), 709 );
+ message.addRepeatedField(f("packed_sfixed64"), 710L);
+ message.addRepeatedField(f("packed_float" ), 711F);
+ message.addRepeatedField(f("packed_double" ), 712D);
+ message.addRepeatedField(f("packed_bool" ), false);
+ message.addRepeatedField(f("packed_enum" ), foreignBaz);
+ }
+
+ public void assertPackedFieldsSetViaReflection(Message message) {
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_int32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_int64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_uint32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_uint64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sint32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sint64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_fixed32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_fixed64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sfixed32")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sfixed64")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_float" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_double" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_bool" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_enum" )));
+ Assert.assertEquals(601 , message.getRepeatedField(f("packed_int32" ), 0));
+ Assert.assertEquals(602L , message.getRepeatedField(f("packed_int64" ), 0));
+ Assert.assertEquals(603 , message.getRepeatedField(f("packed_uint32" ), 0));
+ Assert.assertEquals(604L , message.getRepeatedField(f("packed_uint64" ), 0));
+ Assert.assertEquals(605 , message.getRepeatedField(f("packed_sint32" ), 0));
+ Assert.assertEquals(606L , message.getRepeatedField(f("packed_sint64" ), 0));
+ Assert.assertEquals(607 , message.getRepeatedField(f("packed_fixed32" ), 0));
+ Assert.assertEquals(608L , message.getRepeatedField(f("packed_fixed64" ), 0));
+ Assert.assertEquals(609 , message.getRepeatedField(f("packed_sfixed32"), 0));
+ Assert.assertEquals(610L , message.getRepeatedField(f("packed_sfixed64"), 0));
+ Assert.assertEquals(611F , message.getRepeatedField(f("packed_float" ), 0));
+ Assert.assertEquals(612D , message.getRepeatedField(f("packed_double" ), 0));
+ Assert.assertEquals(true , message.getRepeatedField(f("packed_bool" ), 0));
+ Assert.assertEquals(foreignBar, message.getRepeatedField(f("packed_enum" ),0));
+ Assert.assertEquals(701 , message.getRepeatedField(f("packed_int32" ), 1));
+ Assert.assertEquals(702L , message.getRepeatedField(f("packed_int64" ), 1));
+ Assert.assertEquals(703 , message.getRepeatedField(f("packed_uint32" ), 1));
+ Assert.assertEquals(704L , message.getRepeatedField(f("packed_uint64" ), 1));
+ Assert.assertEquals(705 , message.getRepeatedField(f("packed_sint32" ), 1));
+ Assert.assertEquals(706L , message.getRepeatedField(f("packed_sint64" ), 1));
+ Assert.assertEquals(707 , message.getRepeatedField(f("packed_fixed32" ), 1));
+ Assert.assertEquals(708L , message.getRepeatedField(f("packed_fixed64" ), 1));
+ Assert.assertEquals(709 , message.getRepeatedField(f("packed_sfixed32"), 1));
+ Assert.assertEquals(710L , message.getRepeatedField(f("packed_sfixed64"), 1));
+ Assert.assertEquals(711F , message.getRepeatedField(f("packed_float" ), 1));
+ Assert.assertEquals(712D , message.getRepeatedField(f("packed_double" ), 1));
+ Assert.assertEquals(false, message.getRepeatedField(f("packed_bool" ), 1));
+ Assert.assertEquals(foreignBaz, message.getRepeatedField(f("packed_enum" ),1));
+ }
+
+ /**
+ * Verifies that the reflection setters for the given.Builder object throw a
+ * NullPointerException if they are passed a null value. Uses Assert to throw an
+ * appropriate assertion failure, if the condition is not verified.
+ */
+ public void assertReflectionSettersRejectNull(Message.Builder builder)
+ throws Exception {
+ try {
+ builder.setField(f("optional_string"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setField(f("optional_bytes"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setField(f("optional_nested_enum"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setField(f("optional_nested_message"),
+ (TestAllTypes.NestedMessage) null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setField(f("optional_nested_message"),
+ (TestAllTypes.NestedMessage.Builder) null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ try {
+ builder.addRepeatedField(f("repeated_string"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedField(f("repeated_bytes"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedField(f("repeated_nested_enum"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedField(f("repeated_nested_message"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ }
+
+ /**
+ * Verifies that the reflection repeated setters for the given Builder object throw a
+ * NullPointerException if they are passed a null value. Uses Assert to throw an appropriate
+ * assertion failure, if the condition is not verified.
+ */
+ public void assertReflectionRepeatedSettersRejectNull(Message.Builder builder)
+ throws Exception {
+ builder.addRepeatedField(f("repeated_string"), "one");
+ try {
+ builder.setRepeatedField(f("repeated_string"), 0, null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ builder.addRepeatedField(f("repeated_bytes"), toBytes("one"));
+ try {
+ builder.setRepeatedField(f("repeated_bytes"), 0, null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ builder.addRepeatedField(f("repeated_nested_enum"), nestedBaz);
+ try {
+ builder.setRepeatedField(f("repeated_nested_enum"), 0, null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ builder.addRepeatedField(
+ f("repeated_nested_message"),
+ TestAllTypes.NestedMessage.newBuilder().setBb(218).build());
+ try {
+ builder.setRepeatedField(f("repeated_nested_message"), 0, null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ }
}
/**
@@ -2344,4 +2781,21 @@ class TestUtil {
return goldenMessage;
}
private static ByteString goldenMessage = null;
+
+ /**
+ * Get the bytes of the "golden packed fields message". This is a serialized
+ * TestPackedTypes with all fields set as they would be by
+ * {@link setPackedFields(TestPackedTypes.Builder)}, but it is loaded from a
+ * file on disk rather than generated dynamically. The file is actually
+ * generated by C++ code, so testing against it verifies compatibility with
+ * C++.
+ */
+ public static ByteString getGoldenPackedFieldsMessage() {
+ if (goldenPackedFieldsMessage == null) {
+ goldenPackedFieldsMessage =
+ readBytesFromFile("golden_packed_fields_message");
+ }
+ return goldenPackedFieldsMessage;
+ }
+ private static ByteString goldenPackedFieldsMessage = null;
}
diff --git a/java/src/test/java/com/google/protobuf/TextFormatTest.java b/java/src/test/java/com/google/protobuf/TextFormatTest.java
index 9557bdf6..ec4910a3 100644
--- a/java/src/test/java/com/google/protobuf/TextFormatTest.java
+++ b/java/src/test/java/com/google/protobuf/TextFormatTest.java
@@ -586,4 +586,32 @@ public class TextFormatTest extends TestCase {
// success
}
}
+
+ public void testParseLongString() throws Exception {
+ String longText =
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890";
+
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge("optional_string: \"" + longText + "\"", builder);
+ assertEquals(longText, builder.getOptionalString());
+ }
}
diff --git a/java/src/test/java/com/google/protobuf/WireFormatTest.java b/java/src/test/java/com/google/protobuf/WireFormatTest.java
index 3fb54fcf..48453faf 100644
--- a/java/src/test/java/com/google/protobuf/WireFormatTest.java
+++ b/java/src/test/java/com/google/protobuf/WireFormatTest.java
@@ -32,9 +32,11 @@ package com.google.protobuf;
import junit.framework.TestCase;
import protobuf_unittest.UnittestProto;
-import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestFieldOrderings;
+import protobuf_unittest.UnittestProto.TestPackedExtensions;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
import protobuf_unittest.UnittestMset.TestMessageSet;
import protobuf_unittest.UnittestMset.RawMessageSet;
import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
@@ -57,9 +59,20 @@ public class WireFormatTest extends TestCase {
TestUtil.assertAllFieldsSet(message2);
}
+ public void testSerializationPacked() throws Exception {
+ TestPackedTypes message = TestUtil.getPackedSet();
+
+ ByteString rawBytes = message.toByteString();
+ assertEquals(rawBytes.size(), message.getSerializedSize());
+
+ TestPackedTypes message2 = TestPackedTypes.parseFrom(rawBytes);
+
+ TestUtil.assertPackedFieldsSet(message2);
+ }
+
public void testSerializeExtensions() throws Exception {
// TestAllTypes and TestAllExtensions should have compatible wire formats,
- // so if we serealize a TestAllExtensions then parse it as TestAllTypes
+ // so if we serialize a TestAllExtensions then parse it as TestAllTypes
// it should work.
TestAllExtensions message = TestUtil.getAllExtensionsSet();
@@ -71,17 +84,27 @@ public class WireFormatTest extends TestCase {
TestUtil.assertAllFieldsSet(message2);
}
+ public void testSerializePackedExtensions() throws Exception {
+ // TestPackedTypes and TestPackedExtensions should have compatible wire
+ // formats; check that they serialize to the same string.
+ TestPackedExtensions message = TestUtil.getPackedExtensionsSet();
+ ByteString rawBytes = message.toByteString();
+
+ TestPackedTypes message2 = TestUtil.getPackedSet();
+ ByteString rawBytes2 = message2.toByteString();
+
+ assertEquals(rawBytes, rawBytes2);
+ }
+
public void testParseExtensions() throws Exception {
// TestAllTypes and TestAllExtensions should have compatible wire formats,
- // so if we serealize a TestAllTypes then parse it as TestAllExtensions
+ // so if we serialize a TestAllTypes then parse it as TestAllExtensions
// it should work.
TestAllTypes message = TestUtil.getAllSet();
ByteString rawBytes = message.toByteString();
- ExtensionRegistry registry = ExtensionRegistry.newInstance();
- TestUtil.registerAllExtensions(registry);
- registry = registry.getUnmodifiable();
+ ExtensionRegistry registry = TestUtil.getExtensionRegistry();
TestAllExtensions message2 =
TestAllExtensions.parseFrom(rawBytes, registry);
@@ -89,6 +112,19 @@ public class WireFormatTest extends TestCase {
TestUtil.assertAllExtensionsSet(message2);
}
+ public void testParsePackedExtensions() throws Exception {
+ // Ensure that packed extensions can be properly parsed.
+ TestPackedExtensions message = TestUtil.getPackedExtensionsSet();
+ ByteString rawBytes = message.toByteString();
+
+ ExtensionRegistry registry = TestUtil.getExtensionRegistry();
+
+ TestPackedExtensions message2 =
+ TestPackedExtensions.parseFrom(rawBytes, registry);
+
+ TestUtil.assertPackedExtensionsSet(message2);
+ }
+
public void testExtensionsSerializedSize() throws Exception {
assertEquals(TestUtil.getAllSet().getSerializedSize(),
TestUtil.getAllExtensionsSet().getSerializedSize());
@@ -279,4 +315,3 @@ public class WireFormatTest extends TestCase {
assertEquals("bar", field.getLengthDelimitedList().get(0).toStringUtf8());
}
}
-
diff --git a/python/google/protobuf/internal/containers.py b/python/google/protobuf/internal/containers.py
index 14fe863e..fa1e3402 100755
--- a/python/google/protobuf/internal/containers.py
+++ b/python/google/protobuf/internal/containers.py
@@ -106,6 +106,19 @@ class RepeatedScalarFieldContainer(BaseContainer):
if len(self._values) == 1:
self._message_listener.TransitionToNonempty()
+ def extend(self, elem_seq):
+ """Extends by appending the given sequence. Similar to list.extend()."""
+ if not elem_seq:
+ return
+
+ orig_empty = len(self._values) == 0
+ for elem in elem_seq:
+ self._type_checker.CheckValue(elem)
+ self._values.extend(elem_seq)
+ self._message_listener.ByteSizeDirty()
+ if orig_empty:
+ self._message_listener.TransitionToNonempty()
+
def remove(self, elem):
"""Removes an item from the list. Similar to list.remove()."""
self._values.remove(elem)
diff --git a/python/google/protobuf/internal/decoder_test.py b/python/google/protobuf/internal/decoder_test.py
index abcc07fc..e186e14d 100755
--- a/python/google/protobuf/internal/decoder_test.py
+++ b/python/google/protobuf/internal/decoder_test.py
@@ -57,7 +57,7 @@ class DecoderTest(unittest.TestCase):
for expected_field_number in (1, 15, 16, 2047, 2048):
for expected_wire_type in range(6): # Highest-numbered wiretype is 5.
e = encoder.Encoder()
- e._AppendTag(expected_field_number, expected_wire_type)
+ e.AppendTag(expected_field_number, expected_wire_type)
s = e.ToString()
d = decoder.Decoder(s)
field_number, wire_type = d.ReadFieldNumberAndWireType()
diff --git a/python/google/protobuf/internal/encoder.py b/python/google/protobuf/internal/encoder.py
index 7071241c..eed8c8bd 100755
--- a/python/google/protobuf/internal/encoder.py
+++ b/python/google/protobuf/internal/encoder.py
@@ -58,89 +58,161 @@ class Encoder(object):
"""Returns all values encoded in this object as a string."""
return self._stream.ToString()
- # All the Append*() methods below first append a tag+type pair to the buffer
- # before appending the specified value.
-
- def AppendInt32(self, field_number, value):
+ # Append*NoTag methods. These are necessary for serializing packed
+ # repeated fields. The Append*() methods call these methods to do
+ # the actual serialization.
+ def AppendInt32NoTag(self, value):
"""Appends a 32-bit integer to our buffer, varint-encoded."""
- self._AppendTag(field_number, wire_format.WIRETYPE_VARINT)
self._stream.AppendVarint32(value)
- def AppendInt64(self, field_number, value):
+ def AppendInt64NoTag(self, value):
"""Appends a 64-bit integer to our buffer, varint-encoded."""
- self._AppendTag(field_number, wire_format.WIRETYPE_VARINT)
self._stream.AppendVarint64(value)
- def AppendUInt32(self, field_number, unsigned_value):
+ def AppendUInt32NoTag(self, unsigned_value):
"""Appends an unsigned 32-bit integer to our buffer, varint-encoded."""
- self._AppendTag(field_number, wire_format.WIRETYPE_VARINT)
self._stream.AppendVarUInt32(unsigned_value)
- def AppendUInt64(self, field_number, unsigned_value):
+ def AppendUInt64NoTag(self, unsigned_value):
"""Appends an unsigned 64-bit integer to our buffer, varint-encoded."""
- self._AppendTag(field_number, wire_format.WIRETYPE_VARINT)
self._stream.AppendVarUInt64(unsigned_value)
- def AppendSInt32(self, field_number, value):
+ def AppendSInt32NoTag(self, value):
"""Appends a 32-bit integer to our buffer, zigzag-encoded and then
varint-encoded.
"""
- self._AppendTag(field_number, wire_format.WIRETYPE_VARINT)
zigzag_value = wire_format.ZigZagEncode(value)
self._stream.AppendVarUInt32(zigzag_value)
- def AppendSInt64(self, field_number, value):
+ def AppendSInt64NoTag(self, value):
"""Appends a 64-bit integer to our buffer, zigzag-encoded and then
varint-encoded.
"""
- self._AppendTag(field_number, wire_format.WIRETYPE_VARINT)
zigzag_value = wire_format.ZigZagEncode(value)
self._stream.AppendVarUInt64(zigzag_value)
- def AppendFixed32(self, field_number, unsigned_value):
+ def AppendFixed32NoTag(self, unsigned_value):
"""Appends an unsigned 32-bit integer to our buffer, in little-endian
byte-order.
"""
- self._AppendTag(field_number, wire_format.WIRETYPE_FIXED32)
self._stream.AppendLittleEndian32(unsigned_value)
- def AppendFixed64(self, field_number, unsigned_value):
+ def AppendFixed64NoTag(self, unsigned_value):
"""Appends an unsigned 64-bit integer to our buffer, in little-endian
byte-order.
"""
- self._AppendTag(field_number, wire_format.WIRETYPE_FIXED64)
self._stream.AppendLittleEndian64(unsigned_value)
- def AppendSFixed32(self, field_number, value):
+ def AppendSFixed32NoTag(self, value):
"""Appends a signed 32-bit integer to our buffer, in little-endian
byte-order.
"""
sign = (value & 0x80000000) and -1 or 0
if value >> 32 != sign:
raise message.EncodeError('SFixed32 out of range: %d' % value)
- self._AppendTag(field_number, wire_format.WIRETYPE_FIXED32)
self._stream.AppendLittleEndian32(value & 0xffffffff)
- def AppendSFixed64(self, field_number, value):
+ def AppendSFixed64NoTag(self, value):
"""Appends a signed 64-bit integer to our buffer, in little-endian
byte-order.
"""
sign = (value & 0x8000000000000000) and -1 or 0
if value >> 64 != sign:
raise message.EncodeError('SFixed64 out of range: %d' % value)
- self._AppendTag(field_number, wire_format.WIRETYPE_FIXED64)
self._stream.AppendLittleEndian64(value & 0xffffffffffffffff)
- def AppendFloat(self, field_number, value):
+ def AppendFloatNoTag(self, value):
"""Appends a floating-point number to our buffer."""
- self._AppendTag(field_number, wire_format.WIRETYPE_FIXED32)
self._stream.AppendRawBytes(struct.pack('f', value))
- def AppendDouble(self, field_number, value):
+ def AppendDoubleNoTag(self, value):
"""Appends a double-precision floating-point number to our buffer."""
- self._AppendTag(field_number, wire_format.WIRETYPE_FIXED64)
self._stream.AppendRawBytes(struct.pack('d', value))
+ def AppendBoolNoTag(self, value):
+ """Appends a boolean to our buffer."""
+ self.AppendInt32NoTag(value)
+
+ def AppendEnumNoTag(self, value):
+ """Appends an enum value to our buffer."""
+ self.AppendInt32NoTag(value)
+
+
+ # All the Append*() methods below first append a tag+type pair to the buffer
+ # before appending the specified value.
+
+ def AppendInt32(self, field_number, value):
+ """Appends a 32-bit integer to our buffer, varint-encoded."""
+ self.AppendTag(field_number, wire_format.WIRETYPE_VARINT)
+ self.AppendInt32NoTag(value)
+
+ def AppendInt64(self, field_number, value):
+ """Appends a 64-bit integer to our buffer, varint-encoded."""
+ self.AppendTag(field_number, wire_format.WIRETYPE_VARINT)
+ self.AppendInt64NoTag(value)
+
+ def AppendUInt32(self, field_number, unsigned_value):
+ """Appends an unsigned 32-bit integer to our buffer, varint-encoded."""
+ self.AppendTag(field_number, wire_format.WIRETYPE_VARINT)
+ self.AppendUInt32NoTag(unsigned_value)
+
+ def AppendUInt64(self, field_number, unsigned_value):
+ """Appends an unsigned 64-bit integer to our buffer, varint-encoded."""
+ self.AppendTag(field_number, wire_format.WIRETYPE_VARINT)
+ self.AppendUInt64NoTag(unsigned_value)
+
+ def AppendSInt32(self, field_number, value):
+ """Appends a 32-bit integer to our buffer, zigzag-encoded and then
+ varint-encoded.
+ """
+ self.AppendTag(field_number, wire_format.WIRETYPE_VARINT)
+ self.AppendSInt32NoTag(value)
+
+ def AppendSInt64(self, field_number, value):
+ """Appends a 64-bit integer to our buffer, zigzag-encoded and then
+ varint-encoded.
+ """
+ self.AppendTag(field_number, wire_format.WIRETYPE_VARINT)
+ self.AppendSInt64NoTag(value)
+
+ def AppendFixed32(self, field_number, unsigned_value):
+ """Appends an unsigned 32-bit integer to our buffer, in little-endian
+ byte-order.
+ """
+ self.AppendTag(field_number, wire_format.WIRETYPE_FIXED32)
+ self.AppendFixed32NoTag(unsigned_value)
+
+ def AppendFixed64(self, field_number, unsigned_value):
+ """Appends an unsigned 64-bit integer to our buffer, in little-endian
+ byte-order.
+ """
+ self.AppendTag(field_number, wire_format.WIRETYPE_FIXED64)
+ self.AppendFixed64NoTag(unsigned_value)
+
+ def AppendSFixed32(self, field_number, value):
+ """Appends a signed 32-bit integer to our buffer, in little-endian
+ byte-order.
+ """
+ self.AppendTag(field_number, wire_format.WIRETYPE_FIXED32)
+ self.AppendSFixed32NoTag(value)
+
+ def AppendSFixed64(self, field_number, value):
+ """Appends a signed 64-bit integer to our buffer, in little-endian
+ byte-order.
+ """
+ self.AppendTag(field_number, wire_format.WIRETYPE_FIXED64)
+ self.AppendSFixed64NoTag(value)
+
+ def AppendFloat(self, field_number, value):
+ """Appends a floating-point number to our buffer."""
+ self.AppendTag(field_number, wire_format.WIRETYPE_FIXED32)
+ self.AppendFloatNoTag(value)
+
+ def AppendDouble(self, field_number, value):
+ """Appends a double-precision floating-point number to our buffer."""
+ self.AppendTag(field_number, wire_format.WIRETYPE_FIXED64)
+ self.AppendDoubleNoTag(value)
+
def AppendBool(self, field_number, value):
"""Appends a boolean to our buffer."""
self.AppendInt32(field_number, value)
@@ -159,7 +231,7 @@ class Encoder(object):
"""Appends a length-prefixed sequence of bytes to our buffer, with the
length varint-encoded.
"""
- self._AppendTag(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
+ self.AppendTag(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
self._stream.AppendVarUInt32(len(value))
self._stream.AppendRawBytes(value)
@@ -174,14 +246,14 @@ class Encoder(object):
def AppendGroup(self, field_number, group):
"""Appends a group to our buffer.
"""
- self._AppendTag(field_number, wire_format.WIRETYPE_START_GROUP)
+ self.AppendTag(field_number, wire_format.WIRETYPE_START_GROUP)
self._stream.AppendRawBytes(group.SerializeToString())
- self._AppendTag(field_number, wire_format.WIRETYPE_END_GROUP)
+ self.AppendTag(field_number, wire_format.WIRETYPE_END_GROUP)
def AppendMessage(self, field_number, msg):
"""Appends a nested message to our buffer.
"""
- self._AppendTag(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
+ self.AppendTag(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
self._stream.AppendVarUInt32(msg.ByteSize())
self._stream.AppendRawBytes(msg.SerializeToString())
@@ -196,11 +268,11 @@ class Encoder(object):
}
}
"""
- self._AppendTag(1, wire_format.WIRETYPE_START_GROUP)
+ self.AppendTag(1, wire_format.WIRETYPE_START_GROUP)
self.AppendInt32(2, field_number)
self.AppendMessage(3, msg)
- self._AppendTag(1, wire_format.WIRETYPE_END_GROUP)
+ self.AppendTag(1, wire_format.WIRETYPE_END_GROUP)
- def _AppendTag(self, field_number, wire_type):
+ def AppendTag(self, field_number, wire_type):
"""Appends a tag containing field number and wire type information."""
self._stream.AppendVarUInt32(wire_format.PackTag(field_number, wire_type))
diff --git a/python/google/protobuf/internal/encoder_test.py b/python/google/protobuf/internal/encoder_test.py
index 61668223..83a21c39 100755
--- a/python/google/protobuf/internal/encoder_test.py
+++ b/python/google/protobuf/internal/encoder_test.py
@@ -59,7 +59,8 @@ class EncoderTest(unittest.TestCase):
def AppendScalarTestHelper(self, test_name, encoder_method,
expected_stream_method_name,
wire_type, field_value,
- expected_value=None, expected_length=None):
+ expected_value=None, expected_length=None,
+ is_tag_test=True):
"""Helper for testAppendScalars.
Calls one of the Encoder methods, and ensures that the Encoder
@@ -67,9 +68,10 @@ class EncoderTest(unittest.TestCase):
Args:
test_name: Name of this test, used only for logging.
- encoder_method: Callable on self.encoder, which should
- accept |field_value| as an argument. This is the Encoder
- method we're testing.
+ encoder_method: Callable on self.encoder. This is the Encoder
+ method we're testing. If is_tag_test=True, the encoder method
+ accepts a field_number and field_value. if is_tag_test=False,
+ the encoder method accepts a field_value.
expected_stream_method_name: (string) Name of the OutputStream
method we expect Encoder to call to actually put the value
on the wire.
@@ -83,6 +85,9 @@ class EncoderTest(unittest.TestCase):
expected_length: The length we expect Encoder to pass to the
AppendVarUInt32 method. If None we expect the length of the
field_value.
+ is_tag_test: A Boolean. If True (the default), we append the
+ the packed field number and wire_type to the stream before
+ the field value.
"""
if expected_value is None:
expected_value = field_value
@@ -93,14 +98,16 @@ class EncoderTest(unittest.TestCase):
test_name, encoder_method, field_value,
expected_stream_method_name, expected_value))
- field_number = 10
- # Should first append the field number and type information.
- self.mock_stream.AppendVarUInt32(self.PackTag(field_number, wire_type))
- # If we're length-delimited, we should then append the length.
- if wire_type == wire_format.WIRETYPE_LENGTH_DELIMITED:
- if expected_length is None:
- expected_length = len(field_value)
- self.mock_stream.AppendVarUInt32(expected_length)
+ if is_tag_test:
+ field_number = 10
+ # Should first append the field number and type information.
+ self.mock_stream.AppendVarUInt32(self.PackTag(field_number, wire_type))
+ # If we're length-delimited, we should then append the length.
+ if wire_type == wire_format.WIRETYPE_LENGTH_DELIMITED:
+ if expected_length is None:
+ expected_length = len(field_value)
+ self.mock_stream.AppendVarUInt32(expected_length)
+
# Should then append the value itself.
# We have to use names instead of methods to work around some
# mox weirdness. (ResetAll() is overzealous).
@@ -109,7 +116,10 @@ class EncoderTest(unittest.TestCase):
expected_stream_method(expected_value)
self.mox.ReplayAll()
- encoder_method(field_number, field_value)
+ if is_tag_test:
+ encoder_method(field_number, field_value)
+ else:
+ encoder_method(field_value)
self.mox.VerifyAll()
self.mox.ResetAll()
@@ -160,6 +170,40 @@ class EncoderTest(unittest.TestCase):
for args in scalar_tests:
self.AppendScalarTestHelper(*args)
+ def testAppendScalarsWithoutTags(self):
+ scalar_no_tag_tests = [
+ ['int32', self.encoder.AppendInt32NoTag, 'AppendVarint32', None, 0],
+ ['int64', self.encoder.AppendInt64NoTag, 'AppendVarint64', None, 0],
+ ['uint32', self.encoder.AppendUInt32NoTag, 'AppendVarUInt32', None, 0],
+ ['uint64', self.encoder.AppendUInt64NoTag, 'AppendVarUInt64', None, 0],
+ ['fixed32', self.encoder.AppendFixed32NoTag,
+ 'AppendLittleEndian32', None, 0],
+ ['fixed64', self.encoder.AppendFixed64NoTag,
+ 'AppendLittleEndian64', None, 0],
+ ['sfixed32', self.encoder.AppendSFixed32NoTag,
+ 'AppendLittleEndian32', None, 0],
+ ['sfixed64', self.encoder.AppendSFixed64NoTag,
+ 'AppendLittleEndian64', None, 0],
+ ['float', self.encoder.AppendFloatNoTag,
+ 'AppendRawBytes', None, 0.0, struct.pack('f', 0.0)],
+ ['double', self.encoder.AppendDoubleNoTag,
+ 'AppendRawBytes', None, 0.0, struct.pack('d', 0.0)],
+ ['bool', self.encoder.AppendBoolNoTag, 'AppendVarint32', None, 0],
+ ['enum', self.encoder.AppendEnumNoTag, 'AppendVarint32', None, 0],
+ ['sint32', self.encoder.AppendSInt32NoTag,
+ 'AppendVarUInt32', None, -1, 1],
+ ['sint64', self.encoder.AppendSInt64NoTag,
+ 'AppendVarUInt64', None, -1, 1],
+ ]
+
+ self.assertEqual(len(scalar_no_tag_tests),
+ len(set(t[0] for t in scalar_no_tag_tests)))
+ self.assert_(len(scalar_no_tag_tests) >=
+ len(set(t[1] for t in scalar_no_tag_tests)))
+ for args in scalar_no_tag_tests:
+ # For no tag tests, the wire_type is not used, so we put in None.
+ self.AppendScalarTestHelper(is_tag_test=False, *args)
+
def testAppendGroup(self):
field_number = 23
# Should first append the start-group marker.
diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py
index 14062762..e405f60b 100755
--- a/python/google/protobuf/internal/reflection_test.py
+++ b/python/google/protobuf/internal/reflection_test.py
@@ -229,8 +229,8 @@ class ReflectionTest(unittest.TestCase):
proto.repeated_fixed32.append(1)
proto.repeated_int32.append(5)
proto.repeated_int32.append(11)
- proto.repeated_string.append('foo')
- proto.repeated_string.append('bar')
+ proto.repeated_string.extend(['foo', 'bar'])
+ proto.repeated_string.extend([])
proto.repeated_string.append('baz')
proto.optional_int32 = 21
self.assertEqual(
@@ -757,6 +757,16 @@ class ReflectionTest(unittest.TestCase):
self.assertRaises(KeyError, extendee_proto.HasExtension,
unittest_pb2.repeated_string_extension)
+ def testStaticParseFrom(self):
+ proto1 = unittest_pb2.TestAllTypes()
+ test_util.SetAllFields(proto1)
+
+ string1 = proto1.SerializeToString()
+ proto2 = unittest_pb2.TestAllTypes.FromString(string1)
+
+ # Messages should be equal.
+ self.assertEqual(proto2, proto1)
+
def testMergeFromSingularField(self):
# Test merge with just a singular field.
proto1 = unittest_pb2.TestAllTypes()
@@ -1209,6 +1219,8 @@ class ByteSizeTest(unittest.TestCase):
def setUp(self):
self.proto = unittest_pb2.TestAllTypes()
self.extended_proto = more_extensions_pb2.ExtendedMessage()
+ self.packed_proto = unittest_pb2.TestPackedTypes()
+ self.packed_extended_proto = unittest_pb2.TestPackedExtensions()
def Size(self):
return self.proto.ByteSize()
@@ -1291,6 +1303,11 @@ class ByteSizeTest(unittest.TestCase):
# Also need 2 bytes for each entry for tag.
self.assertEqual(1 + 2 + 2*2, self.Size())
+ def testRepeatedScalarsExtend(self):
+ self.proto.repeated_int32.extend([10, 128]) # 3 bytes.
+ # Also need 2 bytes for each entry for tag.
+ self.assertEqual(1 + 2 + 2*2, self.Size())
+
def testRepeatedScalarsRemove(self):
self.proto.repeated_int32.append(10) # 1 byte.
self.proto.repeated_int32.append(128) # 2 bytes.
@@ -1443,6 +1460,33 @@ class ByteSizeTest(unittest.TestCase):
self.extended_proto.ClearExtension(extension)
self.assertEqual(0, self.extended_proto.ByteSize())
+ def testPackedRepeatedScalars(self):
+ self.assertEqual(0, self.packed_proto.ByteSize())
+
+ self.packed_proto.packed_int32.append(10) # 1 byte.
+ self.packed_proto.packed_int32.append(128) # 2 bytes.
+ # The tag is 2 bytes (the field number is 90), and the varint
+ # storing the length is 1 byte.
+ int_size = 1 + 2 + 3
+ self.assertEqual(int_size, self.packed_proto.ByteSize())
+
+ self.packed_proto.packed_double.append(4.2) # 8 bytes
+ self.packed_proto.packed_double.append(3.25) # 8 bytes
+ # 2 more tag bytes, 1 more length byte.
+ double_size = 8 + 8 + 3
+ self.assertEqual(int_size+double_size, self.packed_proto.ByteSize())
+
+ self.packed_proto.ClearField('packed_int32')
+ self.assertEqual(double_size, self.packed_proto.ByteSize())
+
+ def testPackedExtensions(self):
+ self.assertEqual(0, self.packed_extended_proto.ByteSize())
+ extension = self.packed_extended_proto.Extensions[
+ unittest_pb2.packed_fixed32_extension]
+ extension.extend([1, 2, 3, 4]) # 16 bytes
+ # Tag is 3 bytes.
+ self.assertEqual(19, self.packed_extended_proto.ByteSize())
+
# TODO(robinson): We need cross-language serialization consistency tests.
# Issues to be sure to cover include:
@@ -1686,6 +1730,63 @@ class SerializationTest(unittest.TestCase):
self.assertEqual(2, proto2.b)
self.assertEqual(3, proto2.c)
+ def testSerializedAllPackedFields(self):
+ first_proto = unittest_pb2.TestPackedTypes()
+ second_proto = unittest_pb2.TestPackedTypes()
+ test_util.SetAllPackedFields(first_proto)
+ serialized = first_proto.SerializeToString()
+ self.assertEqual(first_proto.ByteSize(), len(serialized))
+ second_proto.MergeFromString(serialized)
+ self.assertEqual(first_proto, second_proto)
+
+ def testSerializeAllPackedExtensions(self):
+ first_proto = unittest_pb2.TestPackedExtensions()
+ second_proto = unittest_pb2.TestPackedExtensions()
+ test_util.SetAllPackedExtensions(first_proto)
+ serialized = first_proto.SerializeToString()
+ second_proto.MergeFromString(serialized)
+ self.assertEqual(first_proto, second_proto)
+
+ def testMergePackedFromStringWhenSomeFieldsAlreadySet(self):
+ first_proto = unittest_pb2.TestPackedTypes()
+ first_proto.packed_int32.extend([1, 2])
+ first_proto.packed_double.append(3.0)
+ serialized = first_proto.SerializeToString()
+
+ second_proto = unittest_pb2.TestPackedTypes()
+ second_proto.packed_int32.append(3)
+ second_proto.packed_double.extend([1.0, 2.0])
+ second_proto.packed_sint32.append(4)
+
+ second_proto.MergeFromString(serialized)
+ self.assertEqual([3, 1, 2], second_proto.packed_int32)
+ self.assertEqual([1.0, 2.0, 3.0], second_proto.packed_double)
+ self.assertEqual([4], second_proto.packed_sint32)
+
+ def testPackedFieldsWireFormat(self):
+ proto = unittest_pb2.TestPackedTypes()
+ proto.packed_int32.extend([1, 2, 150, 3]) # 1 + 1 + 2 + 1 bytes
+ proto.packed_double.extend([1.0, 1000.0]) # 8 + 8 bytes
+ proto.packed_float.append(2.0) # 4 bytes, will be before double
+ serialized = proto.SerializeToString()
+ self.assertEqual(proto.ByteSize(), len(serialized))
+ d = decoder.Decoder(serialized)
+ ReadTag = d.ReadFieldNumberAndWireType
+ self.assertEqual((90, wire_format.WIRETYPE_LENGTH_DELIMITED), ReadTag())
+ self.assertEqual(1+1+1+2, d.ReadInt32())
+ self.assertEqual(1, d.ReadInt32())
+ self.assertEqual(2, d.ReadInt32())
+ self.assertEqual(150, d.ReadInt32())
+ self.assertEqual(3, d.ReadInt32())
+ self.assertEqual((100, wire_format.WIRETYPE_LENGTH_DELIMITED), ReadTag())
+ self.assertEqual(4, d.ReadInt32())
+ self.assertEqual(2.0, d.ReadFloat())
+ self.assertEqual((101, wire_format.WIRETYPE_LENGTH_DELIMITED), ReadTag())
+ self.assertEqual(8+8, d.ReadInt32())
+ self.assertEqual(1.0, d.ReadDouble())
+ self.assertEqual(1000.0, d.ReadDouble())
+ self.assertTrue(d.EndOfStream())
+
class OptionsTest(unittest.TestCase):
@@ -1697,6 +1798,21 @@ class OptionsTest(unittest.TestCase):
self.assertEqual(False,
proto.DESCRIPTOR.GetOptions().message_set_wire_format)
+ def testPackedOptions(self):
+ proto = unittest_pb2.TestAllTypes()
+ proto.optional_int32 = 1
+ proto.optional_double = 3.0
+ for field_descriptor, _ in proto.ListFields():
+ self.assertEqual(False, field_descriptor.GetOptions().packed)
+
+ proto = unittest_pb2.TestPackedTypes()
+ proto.packed_int32.append(1)
+ proto.packed_double.append(3.0)
+ for field_descriptor, _ in proto.ListFields():
+ self.assertEqual(True, field_descriptor.GetOptions().packed)
+ self.assertEqual(reflection._FieldDescriptor.LABEL_REPEATED,
+ field_descriptor.label)
+
class UtilityTest(unittest.TestCase):
diff --git a/python/google/protobuf/internal/service_reflection_test.py b/python/google/protobuf/internal/service_reflection_test.py
index 29492e16..e04f8252 100755
--- a/python/google/protobuf/internal/service_reflection_test.py
+++ b/python/google/protobuf/internal/service_reflection_test.py
@@ -74,7 +74,7 @@ class FooUnitTest(unittest.TestCase):
rpc_controller.failure_message = None
- service_descriptor = unittest_pb2.TestService.DESCRIPTOR
+ service_descriptor = unittest_pb2.TestService.GetDescriptor()
srvc.CallMethod(service_descriptor.methods[1], rpc_controller,
unittest_pb2.BarRequest(), MyCallback)
self.assertEqual('Method Bar not implemented.',
@@ -118,6 +118,10 @@ class FooUnitTest(unittest.TestCase):
rpc_controller = 'controller'
request = 'request'
+ # GetDescriptor now static, still works as instance method for compatability
+ self.assertEqual(unittest_pb2.TestService_Stub.GetDescriptor(),
+ stub.GetDescriptor())
+
# Invoke method.
stub.Foo(rpc_controller, request, MyCallback)
diff --git a/python/google/protobuf/internal/test_util.py b/python/google/protobuf/internal/test_util.py
index 14dfbc51..2d50bc4a 100755
--- a/python/google/protobuf/internal/test_util.py
+++ b/python/google/protobuf/internal/test_util.py
@@ -366,3 +366,51 @@ def GoldenFile(filename):
'Could not find golden files. This test must be run from within the '
'protobuf source package so that it can read test data files from the '
'C++ source tree.')
+
+
+def SetAllPackedFields(message):
+ """Sets every field in the message to a unique value.
+
+ Args:
+ message: A unittest_pb2.TestPackedTypes instance.
+ """
+ message.packed_int32.extend([101, 102])
+ message.packed_int64.extend([103, 104])
+ message.packed_uint32.extend([105, 106])
+ message.packed_uint64.extend([107, 108])
+ message.packed_sint32.extend([109, 110])
+ message.packed_sint64.extend([111, 112])
+ message.packed_fixed32.extend([113, 114])
+ message.packed_fixed64.extend([115, 116])
+ message.packed_sfixed32.extend([117, 118])
+ message.packed_sfixed64.extend([119, 120])
+ message.packed_float.extend([121.0, 122.0])
+ message.packed_double.extend([122.0, 123.0])
+ message.packed_bool.extend([True, False])
+ message.packed_enum.extend([unittest_pb2.FOREIGN_FOO,
+ unittest_pb2.FOREIGN_BAR])
+
+
+def SetAllPackedExtensions(message):
+ """Sets every extension in the message to a unique value.
+
+ Args:
+ message: A unittest_pb2.TestPackedExtensions instance.
+ """
+ extensions = message.Extensions
+ pb2 = unittest_pb2
+
+ extensions[pb2.packed_int32_extension].append(101)
+ extensions[pb2.packed_int64_extension].append(102)
+ extensions[pb2.packed_uint32_extension].append(103)
+ extensions[pb2.packed_uint64_extension].append(104)
+ extensions[pb2.packed_sint32_extension].append(105)
+ extensions[pb2.packed_sint64_extension].append(106)
+ extensions[pb2.packed_fixed32_extension].append(107)
+ extensions[pb2.packed_fixed64_extension].append(108)
+ extensions[pb2.packed_sfixed32_extension].append(109)
+ extensions[pb2.packed_sfixed64_extension].append(110)
+ extensions[pb2.packed_float_extension].append(111.0)
+ extensions[pb2.packed_double_extension].append(112.0)
+ extensions[pb2.packed_bool_extension].append(True)
+ extensions[pb2.packed_enum_extension].append(pb2.FOREIGN_BAZ)
diff --git a/python/google/protobuf/internal/type_checkers.py b/python/google/protobuf/internal/type_checkers.py
index ba470cf2..c009627f 100755
--- a/python/google/protobuf/internal/type_checkers.py
+++ b/python/google/protobuf/internal/type_checkers.py
@@ -216,6 +216,23 @@ TYPE_TO_SERIALIZE_METHOD = {
}
+TYPE_TO_NOTAG_SERIALIZE_METHOD = {
+ _FieldDescriptor.TYPE_DOUBLE: _Encoder.AppendDoubleNoTag,
+ _FieldDescriptor.TYPE_FLOAT: _Encoder.AppendFloatNoTag,
+ _FieldDescriptor.TYPE_INT64: _Encoder.AppendInt64NoTag,
+ _FieldDescriptor.TYPE_UINT64: _Encoder.AppendUInt64NoTag,
+ _FieldDescriptor.TYPE_INT32: _Encoder.AppendInt32NoTag,
+ _FieldDescriptor.TYPE_FIXED64: _Encoder.AppendFixed64NoTag,
+ _FieldDescriptor.TYPE_FIXED32: _Encoder.AppendFixed32NoTag,
+ _FieldDescriptor.TYPE_BOOL: _Encoder.AppendBoolNoTag,
+ _FieldDescriptor.TYPE_UINT32: _Encoder.AppendUInt32NoTag,
+ _FieldDescriptor.TYPE_ENUM: _Encoder.AppendEnumNoTag,
+ _FieldDescriptor.TYPE_SFIXED32: _Encoder.AppendSFixed32NoTag,
+ _FieldDescriptor.TYPE_SFIXED64: _Encoder.AppendSFixed64NoTag,
+ _FieldDescriptor.TYPE_SINT32: _Encoder.AppendSInt32NoTag,
+ _FieldDescriptor.TYPE_SINT64: _Encoder.AppendSInt64NoTag,
+ }
+
# Maps from field type to expected wiretype.
FIELD_TYPE_TO_WIRE_TYPE = {
_FieldDescriptor.TYPE_DOUBLE: wire_format.WIRETYPE_FIXED64,
diff --git a/python/google/protobuf/internal/wire_format.py b/python/google/protobuf/internal/wire_format.py
index 5f0af11e..531c9b85 100755
--- a/python/google/protobuf/internal/wire_format.py
+++ b/python/google/protobuf/internal/wire_format.py
@@ -120,6 +120,10 @@ def Int32ByteSize(field_number, int32):
return Int64ByteSize(field_number, int32)
+def Int32ByteSizeNoTag(int32):
+ return _VarUInt64ByteSizeNoTag(0xffffffffffffffff & int32)
+
+
def Int64ByteSize(field_number, int64):
# Have to convert to uint before calling UInt64ByteSize().
return UInt64ByteSize(field_number, 0xffffffffffffffff & int64)
@@ -130,7 +134,7 @@ def UInt32ByteSize(field_number, uint32):
def UInt64ByteSize(field_number, uint64):
- return _TagByteSize(field_number) + _VarUInt64ByteSizeNoTag(uint64)
+ return TagByteSize(field_number) + _VarUInt64ByteSizeNoTag(uint64)
def SInt32ByteSize(field_number, int32):
@@ -142,31 +146,31 @@ def SInt64ByteSize(field_number, int64):
def Fixed32ByteSize(field_number, fixed32):
- return _TagByteSize(field_number) + 4
+ return TagByteSize(field_number) + 4
def Fixed64ByteSize(field_number, fixed64):
- return _TagByteSize(field_number) + 8
+ return TagByteSize(field_number) + 8
def SFixed32ByteSize(field_number, sfixed32):
- return _TagByteSize(field_number) + 4
+ return TagByteSize(field_number) + 4
def SFixed64ByteSize(field_number, sfixed64):
- return _TagByteSize(field_number) + 8
+ return TagByteSize(field_number) + 8
def FloatByteSize(field_number, flt):
- return _TagByteSize(field_number) + 4
+ return TagByteSize(field_number) + 4
def DoubleByteSize(field_number, double):
- return _TagByteSize(field_number) + 8
+ return TagByteSize(field_number) + 8
def BoolByteSize(field_number, b):
- return _TagByteSize(field_number) + 1
+ return TagByteSize(field_number) + 1
def EnumByteSize(field_number, enum):
@@ -178,18 +182,18 @@ def StringByteSize(field_number, string):
def BytesByteSize(field_number, b):
- return (_TagByteSize(field_number)
+ return (TagByteSize(field_number)
+ _VarUInt64ByteSizeNoTag(len(b))
+ len(b))
def GroupByteSize(field_number, message):
- return (2 * _TagByteSize(field_number) # START and END group.
+ return (2 * TagByteSize(field_number) # START and END group.
+ message.ByteSize())
def MessageByteSize(field_number, message):
- return (_TagByteSize(field_number)
+ return (TagByteSize(field_number)
+ _VarUInt64ByteSizeNoTag(message.ByteSize())
+ message.ByteSize())
@@ -199,7 +203,7 @@ def MessageSetItemByteSize(field_number, msg):
# There are 2 tags for the beginning and ending of the repeated group, that
# is field number 1, one with field number 2 (type_id) and one with field
# number 3 (message).
- total_size = (2 * _TagByteSize(1) + _TagByteSize(2) + _TagByteSize(3))
+ total_size = (2 * TagByteSize(1) + TagByteSize(2) + TagByteSize(3))
# Add the number of bytes for type_id.
total_size += _VarUInt64ByteSizeNoTag(field_number)
@@ -214,15 +218,14 @@ def MessageSetItemByteSize(field_number, msg):
return total_size
-# Private helper functions for the *ByteSize() functions above.
-
-
-def _TagByteSize(field_number):
+def TagByteSize(field_number):
"""Returns the bytes required to serialize a tag with this field number."""
# Just pass in type 0, since the type won't affect the tag+type size.
return _VarUInt64ByteSizeNoTag(PackTag(field_number, 0))
+# Private helper function for the *ByteSize() functions above.
+
def _VarUInt64ByteSizeNoTag(uint64):
"""Returns the bytes required to serialize a single varint.
uint64 must be unsigned.
diff --git a/python/google/protobuf/reflection.py b/python/google/protobuf/reflection.py
index 9ba752e4..0d5191be 100755
--- a/python/google/protobuf/reflection.py
+++ b/python/google/protobuf/reflection.py
@@ -462,6 +462,12 @@ def _AddStaticMethods(cls):
cls._known_extensions.append(extension_handle)
cls.RegisterExtension = staticmethod(RegisterExtension)
+ def FromString(s):
+ message = cls()
+ message.MergeFromString(s)
+ return message
+ cls.FromString = staticmethod(FromString)
+
def _AddListFieldsMethod(message_descriptor, cls):
"""Helper for _AddMessageMethods()."""
@@ -665,9 +671,36 @@ def _AddByteSizeMethod(message_descriptor, cls):
else:
elements = [value]
- size = sum(_BytesForNonRepeatedElement(element, field_number, field_type)
- for element in elements)
- return size
+ if field.GetOptions().packed:
+ content_size = _ContentBytesForPackedField(message, field, elements)
+ if content_size:
+ tag_size = wire_format.TagByteSize(field_number)
+ length_size = wire_format.Int32ByteSizeNoTag(content_size)
+ return tag_size + length_size + content_size
+ else:
+ return 0
+ else:
+ return sum(_BytesForNonRepeatedElement(element, field_number, field_type)
+ for element in elements)
+
+ def _ContentBytesForPackedField(self, field, value):
+ """Returns the number of bytes required to serialize the actual
+ content of a packed field (not including the tag or the encoding
+ of the length.
+
+ Args:
+ self: The Message instance containing a field of the given type.
+ field: A FieldDescriptor describing the field of interest.
+ value: The value whose byte size we're interested in.
+
+ Returns: The number of bytes required to serialize the current value
+ of the packed "field" in "message", excluding space for tags and the
+ length encoding.
+ """
+ size = sum(_BytesForNonRepeatedElement(element, field.number, field.type)
+ for element in value)
+ # In the packed case, there are no per element tags.
+ return size - wire_format.TagByteSize(field.number) * len(value)
fields = message_descriptor.fields
has_field_names = (_HasFieldName(f.name) for f in fields)
@@ -691,6 +724,8 @@ def _AddByteSizeMethod(message_descriptor, cls):
self._cached_byte_size = size
self._cached_byte_size_dirty = False
return size
+
+ cls._ContentBytesForPackedField = _ContentBytesForPackedField
cls.ByteSize = ByteSize
@@ -788,10 +823,29 @@ def _AddSerializePartialToStringMethod(message_descriptor, cls):
repeated_value = field_value
else:
repeated_value = [field_value]
- for element in repeated_value:
- _SerializeValueToEncoder(element, field_descriptor.number,
- field_descriptor, encoder)
+ if field_descriptor.GetOptions().packed:
+ # First, write the field number and WIRETYPE_LENGTH_DELIMITED.
+ field_number = field_descriptor.number
+ encoder.AppendTag(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
+ # Next, write the number of bytes.
+ content_bytes = self._ContentBytesForPackedField(
+ field_descriptor, field_value)
+ encoder.AppendInt32NoTag(content_bytes)
+ # Finally, write the actual values.
+ try:
+ method = type_checkers.TYPE_TO_NOTAG_SERIALIZE_METHOD[
+ field_descriptor.type]
+ for value in repeated_value:
+ method(encoder, value)
+ except KeyError:
+ raise message_mod.EncodeError('Unrecognized field type: %d' %
+ field_descriptor.type)
+ else:
+ for element in repeated_value:
+ _SerializeValueToEncoder(element, field_descriptor.number,
+ field_descriptor, encoder)
return encoder.ToString()
+
cls.SerializePartialToString = SerializePartialToString
@@ -803,6 +857,14 @@ def _WireTypeForFieldType(field_type):
raise message_mod.DecodeError('Unknown field type: %d' % field_type)
+def _WireTypeForField(field_descriptor):
+ """Given a field descriptor, returns the expected wire type."""
+ if field_descriptor.GetOptions().packed:
+ return wire_format.WIRETYPE_LENGTH_DELIMITED
+ else:
+ return _WireTypeForFieldType(field_descriptor.type)
+
+
def _RecursivelyMerge(field_number, field_type, decoder, message):
"""Decodes a message from decoder into message.
message is either a group or a nested message within some containing
@@ -918,9 +980,11 @@ def _DeserializeMessageSetItem(message, decoder):
def _DeserializeOneEntity(message_descriptor, message, decoder):
"""Deserializes the next wire entity from decoder into message.
- The next wire entity is either a scalar or a nested message,
- and may also be an element in a repeated field (the wire encoding
- is the same).
+
+ The next wire entity is either a scalar or a nested message, an
+ element in a repeated field (the wire encoding in this case is the
+ same), or a packed repeated field (in this case, the entire repeated
+ field is read by a single call to _DeserializeOneEntity).
Args:
message_descriptor: A Descriptor instance describing all fields
@@ -973,14 +1037,14 @@ def _DeserializeOneEntity(message_descriptor, message, decoder):
# if this field is a nonrepeated scalar.
field_number = field_descriptor.number
- field_type = field_descriptor.type
- expected_wire_type = _WireTypeForFieldType(field_type)
+ expected_wire_type = _WireTypeForField(field_descriptor)
if wire_type != expected_wire_type:
# Need to fill in uninterpreted_bytes. Work for the next CL.
raise RuntimeError('TODO(robinson): Wiretype mismatches not handled.')
property_name = _PropertyName(field_descriptor.name)
label = field_descriptor.label
+ field_type = field_descriptor.type
cpp_type = field_descriptor.cpp_type
# Nonrepeated scalar. Just set the field directly.
@@ -1000,8 +1064,17 @@ def _DeserializeOneEntity(message_descriptor, message, decoder):
if cpp_type != _FieldDescriptor.CPPTYPE_MESSAGE:
# Repeated scalar.
- element_list.append(_DeserializeScalarFromDecoder(field_type, decoder))
- return decoder.Position() - initial_position
+ if not field_descriptor.GetOptions().packed:
+ element_list.append(_DeserializeScalarFromDecoder(field_type, decoder))
+ return decoder.Position() - initial_position
+ else:
+ # Packed repeated field.
+ length = _DeserializeScalarFromDecoder(
+ _FieldDescriptor.TYPE_INT32, decoder)
+ content_start = decoder.Position()
+ while decoder.Position() - content_start < length:
+ element_list.append(_DeserializeScalarFromDecoder(field_type, decoder))
+ return decoder.Position() - content_start
else:
# Repeated composite.
composite = element_list.add()
diff --git a/python/google/protobuf/service.py b/python/google/protobuf/service.py
index 3989216a..9ec42fe3 100755
--- a/python/google/protobuf/service.py
+++ b/python/google/protobuf/service.py
@@ -31,7 +31,7 @@
"""Declares the RPC service interfaces.
This module declares the abstract interfaces underlying proto2 RPC
-services. These are intented to be independent of any particular RPC
+services. These are intended to be independent of any particular RPC
implementation, so that proto2 services can be used on top of a variety
of implementations.
"""
@@ -39,6 +39,11 @@ of implementations.
__author__ = 'petar@google.com (Petar Petrov)'
+class RpcException(Exception):
+ """Exception raised on failed blocking RPC method call."""
+ pass
+
+
class Service(object):
"""Abstract base interface for protocol-buffer-based RPC services.
@@ -49,7 +54,7 @@ class Service(object):
its exact type at compile time (analogous to the Message interface).
"""
- def GetDescriptor(self):
+ def GetDescriptor():
"""Retrieves this service's descriptor."""
raise NotImplementedError
@@ -57,6 +62,14 @@ class Service(object):
request, done):
"""Calls a method of the service specified by method_descriptor.
+ If "done" is None then the call is blocking and the response
+ message will be returned directly. Otherwise the call is asynchronous
+ and "done" will later be called with the response value.
+
+ In the blocking case, RpcException will be raised on error.
+ Asynchronous calls must check status via the Failed method of the
+ RpcController.
+
Preconditions:
* method_descriptor.service == GetDescriptor
* request is of the exact same classes as returned by
diff --git a/python/google/protobuf/service_reflection.py b/python/google/protobuf/service_reflection.py
index bdd6bad5..851e83e7 100755
--- a/python/google/protobuf/service_reflection.py
+++ b/python/google/protobuf/service_reflection.py
@@ -142,24 +142,17 @@ class _ServiceBuilder(object):
# instance to the method that does the real CallMethod work.
def _WrapCallMethod(srvc, method_descriptor,
rpc_controller, request, callback):
- self._CallMethod(srvc, method_descriptor,
+ return self._CallMethod(srvc, method_descriptor,
rpc_controller, request, callback)
self.cls = cls
cls.CallMethod = _WrapCallMethod
- cls.GetDescriptor = self._GetDescriptor
+ cls.GetDescriptor = staticmethod(lambda: self.descriptor)
+ cls.GetDescriptor.__doc__ = "Returns the service descriptor."
cls.GetRequestClass = self._GetRequestClass
cls.GetResponseClass = self._GetResponseClass
for method in self.descriptor.methods:
setattr(cls, method.name, self._GenerateNonImplementedMethod(method))
- def _GetDescriptor(self):
- """Retrieves the service descriptor.
-
- Returns:
- The descriptor of the service (of type ServiceDescriptor).
- """
- return self.descriptor
-
def _CallMethod(self, srvc, method_descriptor,
rpc_controller, request, callback):
"""Calls the method described by a given method descriptor.
@@ -175,7 +168,7 @@ class _ServiceBuilder(object):
raise RuntimeError(
'CallMethod() given method descriptor for wrong service type.')
method = getattr(srvc, method_descriptor.name)
- method(rpc_controller, request, callback)
+ return method(rpc_controller, request, callback)
def _GetRequestClass(self, method_descriptor):
"""Returns the class of the request protocol message.
@@ -270,8 +263,8 @@ class _ServiceStubBuilder(object):
setattr(cls, method.name, self._GenerateStubMethod(method))
def _GenerateStubMethod(self, method):
- return lambda inst, rpc_controller, request, callback: self._StubMethod(
- inst, method, rpc_controller, request, callback)
+ return (lambda inst, rpc_controller, request, callback=None:
+ self._StubMethod(inst, method, rpc_controller, request, callback))
def _StubMethod(self, stub, method_descriptor,
rpc_controller, request, callback):
@@ -283,7 +276,9 @@ class _ServiceStubBuilder(object):
rpc_controller: Rpc controller to execute the method.
request: Request protocol message.
callback: A callback to execute when the method finishes.
+ Returns:
+ Response message (in case of blocking call).
"""
- stub.rpc_channel.CallMethod(
+ return stub.rpc_channel.CallMethod(
method_descriptor, rpc_controller, request,
method_descriptor.output_type._concrete_class, callback)
diff --git a/src/Makefile.am b/src/Makefile.am
index c13a723e..18167482 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -160,6 +160,7 @@ EXTRA_DIST = \
$(protoc_inputs) \
solaris/libstdc++.la \
google/protobuf/testdata/golden_message \
+ google/protobuf/testdata/golden_packed_fields_message \
google/protobuf/testdata/text_format_unittest_data.txt \
google/protobuf/testdata/text_format_unittest_extensions_data.txt \
google/protobuf/package_info.h \
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index 089844f4..09473ec7 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -751,7 +751,8 @@ bool CommandLineInterface::GenerateOutput(
if (!output_directive.generator->Generate(
parsed_file, output_directive.parameter, &output_directory, &error)) {
// Generator returned an error.
- cerr << output_directive.name << ": " << error << endl;
+ cerr << parsed_file->name() << ": " << output_directive.name << ": "
+ << error << endl;
return false;
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
index c998f20b..19779a8a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -158,7 +158,13 @@ RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
void RepeatedEnumFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
- printer->Print(variables_, "::google::protobuf::RepeatedField<int> $name$_;\n");
+ printer->Print(variables_,
+ "::google::protobuf::RepeatedField<int> $name$_;\n");
+ if (descriptor_->options().packed() &&
+ descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
+ printer->Print(variables_,
+ "mutable int _$name$_cached_byte_size_;\n");
+ }
}
void RepeatedEnumFieldGenerator::
@@ -217,31 +223,84 @@ GenerateInitializer(io::Printer* printer) const {
void RepeatedEnumFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
- printer->Print(variables_,
- "int value;\n"
- "DO_(::google::protobuf::internal::WireFormat::ReadEnum(input, &value));\n"
- "if ($type$_IsValid(value)) {\n"
- " add_$name$(static_cast< $type$ >(value));\n"
- "} else {\n"
- " mutable_unknown_fields()->AddField($number$)->add_varint(value);\n"
- "}\n");
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "::google::protobuf::uint32 length;\n"
+ "DO_(input->ReadVarint32(&length));\n"
+ "::google::protobuf::io::CodedInputStream::Limit limit = "
+ "input->PushLimit(length);\n"
+ "while (input->BytesUntilLimit() > 0) {\n"
+ " int value;\n"
+ " DO_(::google::protobuf::internal::WireFormat::ReadEnum(input, &value));\n"
+ " if ($type$_IsValid(value)) {\n"
+ " add_$name$(static_cast< $type$ >(value));\n"
+ " }\n"
+ "}\n"
+ "input->PopLimit(limit);\n");
+ } else {
+ printer->Print(variables_,
+ "int value;\n"
+ "DO_(::google::protobuf::internal::WireFormat::ReadEnum(input, &value));\n"
+ "if ($type$_IsValid(value)) {\n"
+ " add_$name$(static_cast< $type$ >(value));\n"
+ "} else {\n"
+ " mutable_unknown_fields()->AddField($number$)->add_varint(value);\n"
+ "}\n");
+ }
}
void RepeatedEnumFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
+ if (descriptor_->options().packed()) {
+ // Write the tag and the size.
+ printer->Print(variables_,
+ "if (this->$name$_size() > 0) {\n"
+ " DO_(::google::protobuf::internal::WireFormat::WriteTag("
+ "$number$, ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED,"
+ "output));\n"
+ " DO_(output->WriteVarint32(_$name$_cached_byte_size_));\n"
+ "}\n");
+ }
printer->Print(variables_,
- "DO_(::google::protobuf::internal::WireFormat::WriteEnum("
- "$number$, this->$name$(i), output));\n");
+ "for (int i = 0; i < this->$name$_size(); i++) {\n");
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ " DO_(::google::protobuf::internal::WireFormat::WriteEnumNoTag("
+ "this->$name$(i), output));\n");
+ } else {
+ printer->Print(variables_,
+ " DO_(::google::protobuf::internal::WireFormat::WriteEnum("
+ "$number$, this->$name$(i), output));\n");
+ }
+ printer->Print("}\n");
}
void RepeatedEnumFieldGenerator::
GenerateByteSize(io::Printer* printer) const {
printer->Print(variables_,
- "total_size += $tag_size$ * $name$_size();\n"
- "for (int i = 0; i < $name$_size(); i++) {\n"
- " total_size += ::google::protobuf::internal::WireFormat::EnumSize(\n"
- " this->$name$(i));\n"
- "}\n");
+ "{\n"
+ " int data_size = 0;\n");
+ printer->Indent();
+ printer->Print(variables_,
+ "for (int i = 0; i < this->$name$_size(); i++) {\n"
+ " data_size += ::google::protobuf::internal::WireFormat::EnumSize(\n"
+ " this->$name$(i));\n"
+ "}\n");
+
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "if (data_size > 0) {\n"
+ " total_size += $tag_size$ + "
+ "::google::protobuf::internal::WireFormat::Int32Size(data_size);\n"
+ "}\n"
+ "_$name$_cached_byte_size_ = data_size;\n"
+ "total_size += data_size;\n");
+ } else {
+ printer->Print(variables_,
+ "total_size += $tag_size$ * this->$name$_size() + data_size;\n");
+ }
+ printer->Outdent();
+ printer->Print("}\n");
}
} // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index eacceeaf..c6843e93 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -41,7 +41,7 @@
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/wire_format.h>
+#include <google/protobuf/wire_format_inl.h>
#include <google/protobuf/descriptor.pb.h>
namespace google {
@@ -1169,10 +1169,9 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
" goto handle_uninterpreted;\n"
" }\n",
"number", SimpleItoa(field->number()),
- "wiretype", kWireTypeNames[
- WireFormat::WireTypeForFieldType(field->type())]);
+ "wiretype", kWireTypeNames[WireFormat::WireTypeForField(field)]);
- if (i > 0 || field->is_repeated()) {
+ if (i > 0 || (field->is_repeated() && !field->options().packed())) {
printer->Print(
" parse_$name$:\n",
"name", field->name());
@@ -1184,7 +1183,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
// switch() is slow since it can't be predicted well. Insert some if()s
// here that attempt to predict the next tag.
- if (field->is_repeated()) {
+ if (field->is_repeated() && !field->options().packed()) {
// Expect repeats of this field.
printer->Print(
"if (input->ExpectTag($tag$)) goto parse_$name$;\n",
@@ -1283,22 +1282,20 @@ void MessageGenerator::GenerateSerializeOneField(
io::Printer* printer, const FieldDescriptor* field) {
PrintFieldComment(printer, field);
- if (field->is_repeated()) {
- printer->Print(
- "for (int i = 0; i < $name$_.size(); i++) {\n",
- "name", FieldName(field));
- } else {
+ if (!field->is_repeated()) {
printer->Print(
"if (_has_bit($index$)) {\n",
"index", SimpleItoa(field->index()));
+ printer->Indent();
}
- printer->Indent();
-
field_generators_.get(field).GenerateSerializeWithCachedSizes(printer);
- printer->Outdent();
- printer->Print("}\n\n");
+ if (!field->is_repeated()) {
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+ printer->Print("\n");
}
void MessageGenerator::GenerateSerializeOneExtensionRange(
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index d1c31067..7d57a6df 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -232,15 +232,17 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
void RepeatedMessageFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
printer->Print(variables_,
- "DO_(::google::protobuf::internal::WireFormat::Write$declared_type$NoVirtual("
- "$number$, this->$name$(i), output));\n");
+ "for (int i = 0; i < this->$name$_size(); i++) {\n"
+ " DO_(::google::protobuf::internal::WireFormat::Write$declared_type$NoVirtual("
+ "$number$, this->$name$(i), output));\n"
+ "}\n");
}
void RepeatedMessageFieldGenerator::
GenerateByteSize(io::Printer* printer) const {
printer->Print(variables_,
- "total_size += $tag_size$ * $name$_size();\n"
- "for (int i = 0; i < $name$_size(); i++) {\n"
+ "total_size += $tag_size$ * this->$name$_size();\n"
+ "for (int i = 0; i < this->$name$_size(); i++) {\n"
" total_size +=\n"
" ::google::protobuf::internal::WireFormat::$declared_type$SizeNoVirtual(\n"
" this->$name$(i));\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
index ef4072f0..768d30cc 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -227,6 +227,11 @@ void RepeatedPrimitiveFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
printer->Print(variables_,
"::google::protobuf::RepeatedField< $type$ > $name$_;\n");
+ if (descriptor_->options().packed() &&
+ descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
+ printer->Print(variables_,
+ "mutable int _$name$_cached_byte_size_;\n");
+ }
}
void RepeatedPrimitiveFieldGenerator::
@@ -283,33 +288,90 @@ GenerateInitializer(io::Printer* printer) const {
void RepeatedPrimitiveFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
- printer->Print(variables_,
- "$type$ value;\n"
- "DO_(::google::protobuf::internal::WireFormat::Read$declared_type$(input, &value));\n"
- "add_$name$(value);\n");
+ if (descriptor_->options().packed()) {
+ printer->Print("{\n");
+ printer->Indent();
+ printer->Print(variables_,
+ "::google::protobuf::uint32 length;\n"
+ "DO_(input->ReadVarint32(&length));\n"
+ "::google::protobuf::io::CodedInputStream::Limit limit = "
+ "input->PushLimit(length);\n"
+ "while (input->BytesUntilLimit() > 0) {\n"
+ " $type$ value;\n"
+ " DO_(::google::protobuf::internal::WireFormat::Read$declared_type$("
+ "input, &value));\n"
+ " add_$name$(value);\n"
+ "}\n"
+ "input->PopLimit(limit);\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ } else {
+ printer->Print(variables_,
+ "$type$ value;\n"
+ "DO_(::google::protobuf::internal::WireFormat::Read$declared_type$("
+ "input, &value));\n"
+ "add_$name$(value);\n");
+ }
}
void RepeatedPrimitiveFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
+ if (descriptor_->options().packed()) {
+ // Write the tag and the size.
+ printer->Print(variables_,
+ "if (this->$name$_size() > 0) {\n"
+ " DO_(::google::protobuf::internal::WireFormat::WriteTag("
+ "$number$, ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED,"
+ "output));\n"
+ " DO_(output->WriteVarint32(_$name$_cached_byte_size_));\n"
+ "}\n");
+ }
printer->Print(variables_,
- "DO_(::google::protobuf::internal::WireFormat::Write$declared_type$("
- "$number$, this->$name$(i), output));\n");
+ "for (int i = 0; i < this->$name$_size(); i++) {\n");
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ " DO_(::google::protobuf::internal::WireFormat::Write$declared_type$NoTag("
+ "this->$name$(i), output));\n");
+ } else {
+ printer->Print(variables_,
+ " DO_(::google::protobuf::internal::WireFormat::Write$declared_type$("
+ "$number$, this->$name$(i), output));\n");
+ }
+ printer->Print("}\n");
}
void RepeatedPrimitiveFieldGenerator::
GenerateByteSize(io::Printer* printer) const {
+ printer->Print(variables_,
+ "{\n"
+ " int data_size = 0;\n");
+ printer->Indent();
int fixed_size = FixedSize(descriptor_->type());
if (fixed_size == -1) {
printer->Print(variables_,
- "total_size += $tag_size$ * $name$_size();\n"
- "for (int i = 0; i < $name$_size(); i++) {\n"
- " total_size += ::google::protobuf::internal::WireFormat::$declared_type$Size(\n"
+ "for (int i = 0; i < this->$name$_size(); i++) {\n"
+ " data_size += ::google::protobuf::internal::WireFormat::$declared_type$Size(\n"
" this->$name$(i));\n"
"}\n");
} else {
printer->Print(variables_,
- "total_size += ($tag_size$ + $fixed_size$) * $name$_size();\n");
+ "data_size = $fixed_size$ * this->$name$_size();\n");
+ }
+
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "if (data_size > 0) {\n"
+ " total_size += $tag_size$ + "
+ "::google::protobuf::internal::WireFormat::Int32Size(data_size);\n"
+ "}\n"
+ "_$name$_cached_byte_size_ = data_size;\n"
+ "total_size += data_size;\n");
+ } else {
+ printer->Print(variables_,
+ "total_size += $tag_size$ * this->$name$_size() + data_size;\n");
}
+ printer->Outdent();
+ printer->Print("}\n");
}
} // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index 3e694ab7..200e3d68 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -374,15 +374,17 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
void RepeatedStringFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
printer->Print(variables_,
- "DO_(::google::protobuf::internal::WireFormat::Write$declared_type$("
- "$number$, this->$name$(i), output));\n");
+ "for (int i = 0; i < this->$name$_size(); i++) {\n"
+ " DO_(::google::protobuf::internal::WireFormat::Write$declared_type$("
+ "$number$, this->$name$(i), output));\n"
+ "}\n");
}
void RepeatedStringFieldGenerator::
GenerateByteSize(io::Printer* printer) const {
printer->Print(variables_,
- "total_size += $tag_size$ * $name$_size();\n"
- "for (int i = 0; i < $name$_size(); i++) {\n"
+ "total_size += $tag_size$ * this->$name$_size();\n"
+ "for (int i = 0; i < this->$name$_size(); i++) {\n"
" total_size += ::google::protobuf::internal::WireFormat::$declared_type$Size(\n"
" this->$name$(i));\n"
"}\n");
diff --git a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
index a4d96ac5..79971a95 100644
--- a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
+++ b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
@@ -54,6 +54,14 @@ message TestConflictingSymbolNames {
optional int32 total_size = 6;
optional int32 tag = 7;
+ enum TestEnum { FOO = 1; }
+ message Data1 { repeated int32 data = 1; }
+ message Data2 { repeated TestEnum data = 1; }
+ message Data3 { repeated string data = 1; }
+ message Data4 { repeated Data4 data = 1; }
+ message Data5 { repeated string data = 1 [ctype=STRING_PIECE]; }
+ message Data6 { repeated string data = 1 [ctype=CORD]; }
+
optional int32 source = 8;
optional int32 value = 9;
optional int32 file = 10;
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index 393c923b..c7e4ee3d 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -225,7 +225,6 @@ TEST(GeneratedMessageTest, ClearOneField) {
TEST(GeneratedMessageTest, CopyFrom) {
unittest::TestAllTypes message1, message2;
- string data;
TestUtil::SetAllFields(&message1);
message2.CopyFrom(message1);
@@ -413,6 +412,13 @@ TEST(GeneratedMessageTest, Serialization) {
EXPECT_TRUE(message2.ParseFromString(data));
TestUtil::ExpectAllFieldsSet(message2);
+
+ unittest::TestPackedTypes packed_message1, packed_message2;
+ string packed_data;
+ TestUtil::SetPackedFields(&packed_message1);
+ packed_message1.SerializeToString(&packed_data);
+ EXPECT_TRUE(packed_message2.ParseFromString(packed_data));
+ TestUtil::ExpectPackedFieldsSet(packed_message2);
}
diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc
index b1484763..4aac6493 100644
--- a/src/google/protobuf/compiler/java/java_enum.cc
+++ b/src/google/protobuf/compiler/java/java_enum.cc
@@ -71,7 +71,8 @@ void EnumGenerator::Generate(io::Printer* printer) {
descriptor_->containing_type() == NULL &&
descriptor_->file()->options().java_multiple_files();
printer->Print(
- "public $static$ enum $classname$ {\n",
+ "public $static$ enum $classname$\n"
+ " implements com.google.protobuf.ProtocolMessageEnum {\n",
"static", is_own_file ? "" : "static",
"classname", descriptor_->name());
printer->Indent();
diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc
index e95fdab4..2153042d 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field.cc
@@ -39,6 +39,7 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/java/java_helpers.h>
#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format_inl.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
@@ -64,6 +65,9 @@ void SetEnumVariables(const FieldDescriptor* descriptor,
(*variables)["number"] = SimpleItoa(descriptor->number());
(*variables)["type"] = type;
(*variables)["default"] = type + "." + default_value->name();
+ (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
+ (*variables)["tag_size"] = SimpleItoa(
+ internal::WireFormat::TagSize(descriptor->number(), descriptor->type()));
}
} // namespace
@@ -97,6 +101,9 @@ GenerateBuilderMembers(io::Printer* printer) const {
" return result.get$capitalized_name$();\n"
"}\n"
"public Builder set$capitalized_name$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
" result.has$capitalized_name$ = true;\n"
" result.$name$_ = value;\n"
" return this;\n"
@@ -176,6 +183,12 @@ GenerateMembers(io::Printer* printer) const {
"public $type$ get$capitalized_name$(int index) {\n"
" return $name$_.get(index);\n"
"}\n");
+
+ if (descriptor_->options().packed() &&
+ descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
+ printer->Print(variables_,
+ "private int $name$MemoizedSerializedSize;\n");
+ }
}
void RepeatedEnumFieldGenerator::
@@ -195,10 +208,16 @@ GenerateBuilderMembers(io::Printer* printer) const {
" return result.get$capitalized_name$(index);\n"
"}\n"
"public Builder set$capitalized_name$(int index, $type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
" result.$name$_.set(index, value);\n"
" return this;\n"
"}\n"
"public Builder add$capitalized_name$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
" if (result.$name$_.isEmpty()) {\n"
" result.$name$_ = new java.util.ArrayList<$type$>();\n"
" }\n"
@@ -241,6 +260,16 @@ GenerateBuildingCode(io::Printer* printer) const {
void RepeatedEnumFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
+ // If packed, set up the while loop
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "int length = input.readRawVarint32();\n"
+ "int oldLimit = input.pushLimit(length);\n"
+ "while(input.getBytesUntilLimit() > 0) {\n");
+ printer->Indent();
+ }
+
+ // Read and store the enum
printer->Print(variables_,
"int rawValue = input.readEnum();\n"
"$type$ value = $type$.valueOf(rawValue);\n"
@@ -249,23 +278,68 @@ GenerateParsingCode(io::Printer* printer) const {
"} else {\n"
" add$capitalized_name$(value);\n"
"}\n");
+
+ if (descriptor_->options().packed()) {
+ printer->Outdent();
+ printer->Print(variables_,
+ "}\n"
+ "input.popLimit(oldLimit);\n");
+ }
}
void RepeatedEnumFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
- printer->Print(variables_,
- "for ($type$ element : get$capitalized_name$List()) {\n"
- " output.writeEnum($number$, element.getNumber());\n"
- "}\n");
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "if (get$capitalized_name$List().size() > 0) {\n"
+ " output.writeRawVarint32($tag$);\n"
+ " output.writeRawVarint32($name$MemoizedSerializedSize);\n"
+ "}\n"
+ "for ($type$ element : get$capitalized_name$List()) {\n"
+ " output.writeEnumNoTag(element.getNumber());\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "for ($type$ element : get$capitalized_name$List()) {\n"
+ " output.writeEnum($number$, element.getNumber());\n"
+ "}\n");
+ }
}
void RepeatedEnumFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
+ "{\n"
+ " int dataSize = 0;\n");
+ printer->Indent();
+
+ printer->Print(variables_,
"for ($type$ element : get$capitalized_name$List()) {\n"
- " size += com.google.protobuf.CodedOutputStream\n"
- " .computeEnumSize($number$, element.getNumber());\n"
+ " dataSize += com.google.protobuf.CodedOutputStream\n"
+ " .computeEnumSizeNoTag(element.getNumber());\n"
"}\n");
+ printer->Print(
+ "size += dataSize;\n");
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "if (!get$capitalized_name$List().isEmpty()) {"
+ " size += $tag_size$;\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeRawVarint32Size(dataSize);\n"
+ "}");
+ } else {
+ printer->Print(variables_,
+ "size += $tag_size$ * get$capitalized_name$List().size();\n");
+ }
+
+ // cache the data size for packed fields.
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "$name$MemoizedSerializedSize = dataSize;\n");
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
}
string RepeatedEnumFieldGenerator::GetBoxedType() const {
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index 3fdd1d57..9a4b2f79 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -41,7 +41,7 @@
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/wire_format.h>
+#include <google/protobuf/wire_format_inl.h>
#include <google/protobuf/descriptor.pb.h>
namespace google {
@@ -500,6 +500,7 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) {
"public static Builder newBuilder($classname$ prototype) {\n"
" return new Builder().mergeFrom(prototype);\n"
"}\n"
+ "public Builder toBuilder() { return newBuilder(this); }\n"
"\n",
"classname", ClassName(descriptor_));
@@ -634,6 +635,13 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
}
printer->Outdent();
+
+ // if message type has extensions
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ " this.mergeExtensionFields(other);\n");
+ }
+
printer->Print(
" this.mergeUnknownFields(other.getUnknownFields());\n"
" return this;\n"
@@ -692,7 +700,7 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) {
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = sorted_fields[i];
uint32 tag = WireFormat::MakeTag(field->number(),
- WireFormat::WireTypeForFieldType(field->type()));
+ WireFormat::WireTypeForField(field));
printer->Print(
"case $tag$: {\n",
diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc
index c85a1598..bbddddde 100644
--- a/src/google/protobuf/compiler/java/java_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_message_field.cc
@@ -94,6 +94,9 @@ GenerateBuilderMembers(io::Printer* printer) const {
" return result.get$capitalized_name$();\n"
"}\n"
"public Builder set$capitalized_name$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
" result.has$capitalized_name$ = true;\n"
" result.$name$_ = value;\n"
" return this;\n"
@@ -216,6 +219,9 @@ GenerateBuilderMembers(io::Printer* printer) const {
" return result.get$capitalized_name$(index);\n"
"}\n"
"public Builder set$capitalized_name$(int index, $type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
" result.$name$_.set(index, value);\n"
" return this;\n"
"}\n"
@@ -225,6 +231,9 @@ GenerateBuilderMembers(io::Printer* printer) const {
" return this;\n"
"}\n"
"public Builder add$capitalized_name$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
" if (result.$name$_.isEmpty()) {\n"
" result.$name$_ = new java.util.ArrayList<$type$>();\n"
" }\n"
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc
index fb4e650f..798e8608 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -39,6 +39,7 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/java/java_helpers.h>
#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format_inl.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
@@ -47,6 +48,8 @@ namespace protobuf {
namespace compiler {
namespace java {
+using internal::WireFormat;
+
namespace {
const char* PrimitiveTypeName(JavaType type) {
@@ -69,6 +72,26 @@ const char* PrimitiveTypeName(JavaType type) {
return NULL;
}
+bool IsReferenceType(JavaType type) {
+ switch (type) {
+ case JAVATYPE_INT : return false;
+ case JAVATYPE_LONG : return false;
+ case JAVATYPE_FLOAT : return false;
+ case JAVATYPE_DOUBLE : return false;
+ case JAVATYPE_BOOLEAN: return false;
+ case JAVATYPE_STRING : return true;
+ case JAVATYPE_BYTES : return true;
+ case JAVATYPE_ENUM : return true;
+ case JAVATYPE_MESSAGE: return true;
+
+ // No default because we want the compiler to complain if any new
+ // JavaTypes are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return false;
+}
+
const char* GetCapitalizedType(const FieldDescriptor* field) {
switch (field->type()) {
case FieldDescriptor::TYPE_INT32 : return "Int32" ;
@@ -108,6 +131,38 @@ bool AllPrintableAscii(const string& text) {
return true;
}
+// For encodings with fixed sizes, returns that size in bytes. Otherwise
+// returns -1.
+int FixedSize(FieldDescriptor::Type type) {
+ switch (type) {
+ case FieldDescriptor::TYPE_INT32 : return -1;
+ case FieldDescriptor::TYPE_INT64 : return -1;
+ case FieldDescriptor::TYPE_UINT32 : return -1;
+ case FieldDescriptor::TYPE_UINT64 : return -1;
+ case FieldDescriptor::TYPE_SINT32 : return -1;
+ case FieldDescriptor::TYPE_SINT64 : return -1;
+ case FieldDescriptor::TYPE_FIXED32 : return WireFormat::kFixed32Size;
+ case FieldDescriptor::TYPE_FIXED64 : return WireFormat::kFixed64Size;
+ case FieldDescriptor::TYPE_SFIXED32: return WireFormat::kSFixed32Size;
+ case FieldDescriptor::TYPE_SFIXED64: return WireFormat::kSFixed64Size;
+ case FieldDescriptor::TYPE_FLOAT : return WireFormat::kFloatSize;
+ case FieldDescriptor::TYPE_DOUBLE : return WireFormat::kDoubleSize;
+
+ case FieldDescriptor::TYPE_BOOL : return WireFormat::kBoolSize;
+ case FieldDescriptor::TYPE_ENUM : return -1;
+
+ case FieldDescriptor::TYPE_STRING : return -1;
+ case FieldDescriptor::TYPE_BYTES : return -1;
+ case FieldDescriptor::TYPE_GROUP : return -1;
+ case FieldDescriptor::TYPE_MESSAGE : return -1;
+
+ // No default because we want the compiler to complain if any new
+ // types are added.
+ }
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return -1;
+}
+
string DefaultValue(const FieldDescriptor* field) {
// Switch on cpp_type since we need to know which default_value_* method
// of FieldDescriptor to call.
@@ -177,8 +232,22 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
(*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
(*variables)["default"] = DefaultValue(descriptor);
(*variables)["capitalized_type"] = GetCapitalizedType(descriptor);
+ (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
+ (*variables)["tag_size"] = SimpleItoa(
+ WireFormat::TagSize(descriptor->number(), descriptor->type()));
+ if (IsReferenceType(GetJavaType(descriptor))) {
+ (*variables)["null_check"] =
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n";
+ } else {
+ (*variables)["null_check"] = "";
+ }
+ int fixed_size = FixedSize(descriptor->type());
+ if (fixed_size != -1) {
+ (*variables)["fixed_size"] = SimpleItoa(fixed_size);
+ }
}
-
} // namespace
// ===================================================================
@@ -210,6 +279,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
" return result.get$capitalized_name$();\n"
"}\n"
"public Builder set$capitalized_name$($type$ value) {\n"
+ "$null_check$"
" result.has$capitalized_name$ = true;\n"
" result.$name$_ = value;\n"
" return this;\n"
@@ -283,6 +353,12 @@ GenerateMembers(io::Printer* printer) const {
"public $type$ get$capitalized_name$(int index) {\n"
" return $name$_.get(index);\n"
"}\n");
+
+ if (descriptor_->options().packed() &&
+ descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
+ printer->Print(variables_,
+ "private int $name$MemoizedSerializedSize;\n");
+ }
}
void RepeatedPrimitiveFieldGenerator::
@@ -302,10 +378,12 @@ GenerateBuilderMembers(io::Printer* printer) const {
" return result.get$capitalized_name$(index);\n"
"}\n"
"public Builder set$capitalized_name$(int index, $type$ value) {\n"
+ "$null_check$"
" result.$name$_.set(index, value);\n"
" return this;\n"
"}\n"
"public Builder add$capitalized_name$($type$ value) {\n"
+ "$null_check$"
" if (result.$name$_.isEmpty()) {\n"
" result.$name$_ = new java.util.ArrayList<$boxed_type$>();\n"
" }\n"
@@ -348,25 +426,80 @@ GenerateBuildingCode(io::Printer* printer) const {
void RepeatedPrimitiveFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
- printer->Print(variables_,
- "add$capitalized_name$(input.read$capitalized_type$());\n");
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "int length = input.readRawVarint32();\n"
+ "int limit = input.pushLimit(length);\n"
+ "while (input.getBytesUntilLimit() > 0) {\n"
+ " add$capitalized_name$(input.read$capitalized_type$());\n"
+ "}\n"
+ "input.popLimit(limit);\n");
+ } else {
+ printer->Print(variables_,
+ "add$capitalized_name$(input.read$capitalized_type$());\n");
+ }
}
void RepeatedPrimitiveFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
- printer->Print(variables_,
- "for ($type$ element : get$capitalized_name$List()) {\n"
- " output.write$capitalized_type$($number$, element);\n"
- "}\n");
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "if (get$capitalized_name$List().size() > 0) {\n"
+ " output.writeRawVarint32($tag$);\n"
+ " output.writeRawVarint32($name$MemoizedSerializedSize);\n"
+ "}\n"
+ "for ($type$ element : get$capitalized_name$List()) {\n"
+ " output.write$capitalized_type$NoTag(element);\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "for ($type$ element : get$capitalized_name$List()) {\n"
+ " output.write$capitalized_type$($number$, element);\n"
+ "}\n");
+ }
}
void RepeatedPrimitiveFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
- "for ($type$ element : get$capitalized_name$List()) {\n"
- " size += com.google.protobuf.CodedOutputStream\n"
- " .compute$capitalized_type$Size($number$, element);\n"
- "}\n");
+ "{\n"
+ " int dataSize = 0;\n");
+ printer->Indent();
+
+ if (FixedSize(descriptor_->type()) == -1) {
+ printer->Print(variables_,
+ "for ($type$ element : get$capitalized_name$List()) {\n"
+ " dataSize += com.google.protobuf.CodedOutputStream\n"
+ " .compute$capitalized_type$SizeNoTag(element);\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n");
+ }
+
+ printer->Print(
+ "size += dataSize;\n");
+
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "if (!get$capitalized_name$List().isEmpty()) {\n"
+ " size += $tag_size$;\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeInt32SizeNoTag(dataSize);\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "size += $tag_size$ * get$capitalized_name$List().size();\n");
+ }
+
+ // cache the data size for packed fields.
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "$name$MemoizedSerializedSize = dataSize;\n");
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
}
string RepeatedPrimitiveFieldGenerator::GetBoxedType() const {
diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
index 754dcbda..ca69fd4c 100644
--- a/src/google/protobuf/compiler/python/python_generator.cc
+++ b/src/google/protobuf/compiler/python/python_generator.cc
@@ -111,7 +111,6 @@ void PrintTopBoilerplate(
io::Printer* printer, const FileDescriptor* file, bool descriptor_proto) {
// TODO(robinson): Allow parameterization of Python version?
printer->Print(
- "#!/usr/bin/python2.4\n"
"# Generated by the protocol buffer compiler. DO NOT EDIT!\n"
"\n"
"from google.protobuf import descriptor\n"
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
index 21c709fb..eb5b5937 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -122,6 +122,35 @@ namespace {
const string kEmptyString;
+string ToCamelCase(const string& input) {
+ bool capitalize_next = false;
+ string result;
+ result.reserve(input.size());
+
+ for (int i = 0; i < input.size(); i++) {
+ if (input[i] == '_') {
+ capitalize_next = true;
+ } else if (capitalize_next) {
+ // Note: I distrust ctype.h due to locales.
+ if ('a' <= input[i] && input[i] <= 'z') {
+ result.push_back(input[i] - 'a' + 'A');
+ } else {
+ result.push_back(input[i]);
+ }
+ capitalize_next = false;
+ } else {
+ result.push_back(input[i]);
+ }
+ }
+
+ // Lower-case the first letter.
+ if (!result.empty() && 'A' <= result[0] && result[0] <= 'Z') {
+ result[0] = result[0] - 'A' + 'a';
+ }
+
+ return result;
+}
+
// A DescriptorPool contains a bunch of hash_maps to implement the
// various Find*By*() methods. Since hashtable lookups are O(1), it's
// most efficient to construct a fixed set of large hash_maps used by
@@ -253,6 +282,9 @@ typedef hash_map<PointerStringPair, Symbol,
typedef hash_map<const char*, const FileDescriptor*,
hash<const char*>, CStringEqual>
FilesByNameMap;
+typedef hash_map<PointerStringPair, const FieldDescriptor*,
+ PointerStringPairHash, PointerStringPairEqual>
+ FieldsByNameMap;
typedef hash_map<DescriptorIntPair, const FieldDescriptor*,
PointerIntegerPairHash<DescriptorIntPair> >
FieldsByNumberMap;
@@ -296,21 +328,29 @@ class DescriptorPool::Tables {
// Finding items.
// Find symbols. These return a null Symbol (symbol.IsNull() is true)
- // if not found. FindSymbolOfType() additionally returns null if the
- // symbol is not of the given type.
+ // if not found.
inline Symbol FindSymbol(const string& key) const;
- inline Symbol FindSymbolOfType(const string& key,
- const Symbol::Type type) const;
inline Symbol FindNestedSymbol(const void* parent,
const string& name) const;
inline Symbol FindNestedSymbolOfType(const void* parent,
const string& name,
const Symbol::Type type) const;
+ // This implements the body of DescriptorPool::Find*ByName(). It should
+ // really be a private method of DescriptorPool, but that would require
+ // declaring Symbol in descriptor.h, which would drag all kinds of other
+ // stuff into the header. Yay C++.
+ Symbol FindByNameHelper(
+ const DescriptorPool* pool, const string& name) const;
+
// These return NULL if not found.
inline const FileDescriptor* FindFile(const string& key) const;
inline const FieldDescriptor* FindFieldByNumber(
const Descriptor* parent, int number) const;
+ inline const FieldDescriptor* FindFieldByLowercaseName(
+ const void* parent, const string& lowercase_name) const;
+ inline const FieldDescriptor* FindFieldByCamelcaseName(
+ const void* parent, const string& camelcase_name) const;
inline const EnumValueDescriptor* FindEnumValueByNumber(
const EnumDescriptor* parent, int number) const;
@@ -330,6 +370,10 @@ class DescriptorPool::Tables {
bool AddFieldByNumber(const FieldDescriptor* field);
bool AddEnumValueByNumber(const EnumValueDescriptor* value);
+ // Adds the field to the lowercase_name and camelcase_name maps. Never
+ // fails because we allow duplicates; the first field by the name wins.
+ void AddFieldByStylizedNames(const FieldDescriptor* field);
+
// Like AddSymbol(), but only adds to symbols_by_parent_, not
// symbols_by_name_. Used for enum values, which need to be registered
// under multiple parents (their type and its parent).
@@ -364,6 +408,8 @@ class DescriptorPool::Tables {
SymbolsByNameMap symbols_by_name_;
SymbolsByParentMap symbols_by_parent_;
FilesByNameMap files_by_name_;
+ FieldsByNameMap fields_by_lowercase_name_;
+ FieldsByNameMap fields_by_camelcase_name_;
FieldsByNumberMap fields_by_number_; // Includes extensions.
EnumValuesByNumberMap enum_values_by_number_;
@@ -373,6 +419,8 @@ class DescriptorPool::Tables {
vector<const char* > symbols_after_checkpoint_;
vector<PointerStringPair> symbols_by_parent_after_checkpoint_;
vector<const char* > files_after_checkpoint_;
+ vector<PointerStringPair> field_lowercase_names_after_checkpoint_;
+ vector<PointerStringPair> field_camelcase_names_after_checkpoint_;
vector<DescriptorIntPair> field_numbers_after_checkpoint_;
vector<EnumIntPair > enum_numbers_after_checkpoint_;
@@ -404,6 +452,8 @@ void DescriptorPool::Tables::Checkpoint() {
symbols_after_checkpoint_.clear();
symbols_by_parent_after_checkpoint_.clear();
files_after_checkpoint_.clear();
+ field_lowercase_names_after_checkpoint_.clear();
+ field_camelcase_names_after_checkpoint_.clear();
field_numbers_after_checkpoint_.clear();
enum_numbers_after_checkpoint_.clear();
}
@@ -418,6 +468,12 @@ void DescriptorPool::Tables::Rollback() {
for (int i = 0; i < files_after_checkpoint_.size(); i++) {
files_by_name_.erase(files_after_checkpoint_[i]);
}
+ for (int i = 0; i < field_lowercase_names_after_checkpoint_.size(); i++) {
+ fields_by_lowercase_name_.erase(field_lowercase_names_after_checkpoint_[i]);
+ }
+ for (int i = 0; i < field_camelcase_names_after_checkpoint_.size(); i++) {
+ fields_by_camelcase_name_.erase(field_camelcase_names_after_checkpoint_[i]);
+ }
for (int i = 0; i < field_numbers_after_checkpoint_.size(); i++) {
fields_by_number_.erase(field_numbers_after_checkpoint_[i]);
}
@@ -428,6 +484,8 @@ void DescriptorPool::Tables::Rollback() {
symbols_after_checkpoint_.clear();
symbols_by_parent_after_checkpoint_.clear();
files_after_checkpoint_.clear();
+ field_lowercase_names_after_checkpoint_.clear();
+ field_camelcase_names_after_checkpoint_.clear();
field_numbers_after_checkpoint_.clear();
enum_numbers_after_checkpoint_.clear();
@@ -455,13 +513,6 @@ inline Symbol DescriptorPool::Tables::FindSymbol(const string& key) const {
}
}
-inline Symbol DescriptorPool::Tables::FindSymbolOfType(
- const string& key, const Symbol::Type type) const {
- Symbol result = FindSymbol(key);
- if (result.type != type) return kNullSymbol;
- return result;
-}
-
inline Symbol DescriptorPool::Tables::FindNestedSymbol(
const void* parent, const string& name) const {
const Symbol* result =
@@ -480,6 +531,27 @@ inline Symbol DescriptorPool::Tables::FindNestedSymbolOfType(
return result;
}
+Symbol DescriptorPool::Tables::FindByNameHelper(
+ const DescriptorPool* pool, const string& name) const {
+ MutexLockMaybe lock(pool->mutex_);
+ Symbol result = FindSymbol(name);
+
+ if (result.IsNull() && pool->underlay_ != NULL) {
+ // Symbol not found; check the underlay.
+ result =
+ pool->underlay_->tables_->FindByNameHelper(pool->underlay_, name);
+ }
+
+ if (result.IsNull()) {
+ // Symbol still not found, so check fallback database.
+ if (pool->TryFindSymbolInFallbackDatabase(name)) {
+ result = FindSymbol(name);
+ }
+ }
+
+ return result;
+}
+
inline const FileDescriptor* DescriptorPool::Tables::FindFile(
const string& key) const {
return FindPtrOrNull(files_by_name_, key.c_str());
@@ -490,6 +562,18 @@ inline const FieldDescriptor* DescriptorPool::Tables::FindFieldByNumber(
return FindPtrOrNull(fields_by_number_, make_pair(parent, number));
}
+inline const FieldDescriptor* DescriptorPool::Tables::FindFieldByLowercaseName(
+ const void* parent, const string& lowercase_name) const {
+ return FindPtrOrNull(fields_by_lowercase_name_,
+ PointerStringPair(parent, lowercase_name.c_str()));
+}
+
+inline const FieldDescriptor* DescriptorPool::Tables::FindFieldByCamelcaseName(
+ const void* parent, const string& camelcase_name) const {
+ return FindPtrOrNull(fields_by_camelcase_name_,
+ PointerStringPair(parent, camelcase_name.c_str()));
+}
+
inline const EnumValueDescriptor* DescriptorPool::Tables::FindEnumValueByNumber(
const EnumDescriptor* parent, int number) const {
return FindPtrOrNull(enum_values_by_number_, make_pair(parent, number));
@@ -537,6 +621,30 @@ bool DescriptorPool::Tables::AddFile(const FileDescriptor* file) {
}
}
+void DescriptorPool::Tables::AddFieldByStylizedNames(
+ const FieldDescriptor* field) {
+ const void* parent;
+ if (field->is_extension()) {
+ if (field->extension_scope() == NULL) {
+ parent = field->file();
+ } else {
+ parent = field->extension_scope();
+ }
+ } else {
+ parent = field->containing_type();
+ }
+
+ PointerStringPair lowercase_key(parent, field->lowercase_name().c_str());
+ if (InsertIfNotPresent(&fields_by_lowercase_name_, lowercase_key, field)) {
+ field_lowercase_names_after_checkpoint_.push_back(lowercase_key);
+ }
+
+ PointerStringPair camelcase_key(parent, field->camelcase_name().c_str());
+ if (InsertIfNotPresent(&fields_by_camelcase_name_, camelcase_key, field)) {
+ field_camelcase_names_after_checkpoint_.push_back(camelcase_key);
+ }
+}
+
bool DescriptorPool::Tables::AddFieldByNumber(const FieldDescriptor* field) {
DescriptorIntPair key(field->containing_type(), field->number());
if (InsertIfNotPresent(&fields_by_number_, key, field)) {
@@ -689,122 +797,55 @@ const FileDescriptor* DescriptorPool::FindFileContainingSymbol(
const Descriptor* DescriptorPool::FindMessageTypeByName(
const string& name) const {
- MutexLockMaybe lock(mutex_);
- Symbol result = tables_->FindSymbolOfType(name, Symbol::MESSAGE);
- if (!result.IsNull()) return result.descriptor;
- if (underlay_ != NULL) {
- const Descriptor* result = underlay_->FindMessageTypeByName(name);
- if (result != NULL) return result;
- }
- if (TryFindSymbolInFallbackDatabase(name)) {
- Symbol result = tables_->FindSymbolOfType(name, Symbol::MESSAGE);
- if (!result.IsNull()) return result.descriptor;
- }
- return NULL;
+ Symbol result = tables_->FindByNameHelper(this, name);
+ return (result.type == Symbol::MESSAGE) ? result.descriptor : NULL;
}
const FieldDescriptor* DescriptorPool::FindFieldByName(
const string& name) const {
- MutexLockMaybe lock(mutex_);
- Symbol result = tables_->FindSymbolOfType(name, Symbol::FIELD);
- if (!result.IsNull() && !result.field_descriptor->is_extension()) {
+ Symbol result = tables_->FindByNameHelper(this, name);
+ if (result.type == Symbol::FIELD &&
+ !result.field_descriptor->is_extension()) {
return result.field_descriptor;
+ } else {
+ return NULL;
}
- if (underlay_ != NULL) {
- const FieldDescriptor* result = underlay_->FindFieldByName(name);
- if (result != NULL) return result;
- }
- if (TryFindSymbolInFallbackDatabase(name)) {
- Symbol result = tables_->FindSymbolOfType(name, Symbol::FIELD);
- if (!result.IsNull() && !result.field_descriptor->is_extension()) {
- return result.field_descriptor;
- }
- }
- return NULL;
}
const FieldDescriptor* DescriptorPool::FindExtensionByName(
const string& name) const {
- MutexLockMaybe lock(mutex_);
- Symbol result = tables_->FindSymbolOfType(name, Symbol::FIELD);
- if (!result.IsNull() && result.field_descriptor->is_extension()) {
+ Symbol result = tables_->FindByNameHelper(this, name);
+ if (result.type == Symbol::FIELD &&
+ result.field_descriptor->is_extension()) {
return result.field_descriptor;
+ } else {
+ return NULL;
}
- if (underlay_ != NULL) {
- const FieldDescriptor* result = underlay_->FindExtensionByName(name);
- if (result != NULL) return result;
- }
- if (TryFindSymbolInFallbackDatabase(name)) {
- Symbol result = tables_->FindSymbolOfType(name, Symbol::FIELD);
- if (!result.IsNull() && result.field_descriptor->is_extension()) {
- return result.field_descriptor;
- }
- }
- return NULL;
}
const EnumDescriptor* DescriptorPool::FindEnumTypeByName(
const string& name) const {
- MutexLockMaybe lock(mutex_);
- Symbol result = tables_->FindSymbolOfType(name, Symbol::ENUM);
- if (!result.IsNull()) return result.enum_descriptor;
- if (underlay_ != NULL) {
- const EnumDescriptor* result = underlay_->FindEnumTypeByName(name);
- if (result != NULL) return result;
- }
- if (TryFindSymbolInFallbackDatabase(name)) {
- Symbol result = tables_->FindSymbolOfType(name, Symbol::ENUM);
- if (!result.IsNull()) return result.enum_descriptor;
- }
- return NULL;
+ Symbol result = tables_->FindByNameHelper(this, name);
+ return (result.type == Symbol::ENUM) ? result.enum_descriptor : NULL;
}
const EnumValueDescriptor* DescriptorPool::FindEnumValueByName(
const string& name) const {
- MutexLockMaybe lock(mutex_);
- Symbol result = tables_->FindSymbolOfType(name, Symbol::ENUM_VALUE);
- if (!result.IsNull()) return result.enum_value_descriptor;
- if (underlay_ != NULL) {
- const EnumValueDescriptor* result = underlay_->FindEnumValueByName(name);
- if (result != NULL) return result;
- }
- if (TryFindSymbolInFallbackDatabase(name)) {
- Symbol result = tables_->FindSymbolOfType(name, Symbol::ENUM_VALUE);
- if (!result.IsNull()) return result.enum_value_descriptor;
- }
- return NULL;
+ Symbol result = tables_->FindByNameHelper(this, name);
+ return (result.type == Symbol::ENUM_VALUE) ?
+ result.enum_value_descriptor : NULL;
}
const ServiceDescriptor* DescriptorPool::FindServiceByName(
const string& name) const {
- MutexLockMaybe lock(mutex_);
- Symbol result = tables_->FindSymbolOfType(name, Symbol::SERVICE);
- if (!result.IsNull()) return result.service_descriptor;
- if (underlay_ != NULL) {
- const ServiceDescriptor* result = underlay_->FindServiceByName(name);
- if (result != NULL) return result;
- }
- if (TryFindSymbolInFallbackDatabase(name)) {
- Symbol result = tables_->FindSymbolOfType(name, Symbol::SERVICE);
- if (!result.IsNull()) return result.service_descriptor;
- }
- return NULL;
+ Symbol result = tables_->FindByNameHelper(this, name);
+ return (result.type == Symbol::SERVICE) ? result.service_descriptor : NULL;
}
const MethodDescriptor* DescriptorPool::FindMethodByName(
const string& name) const {
- MutexLockMaybe lock(mutex_);
- Symbol result = tables_->FindSymbolOfType(name, Symbol::METHOD);
- if (!result.IsNull()) return result.method_descriptor;
- if (underlay_ != NULL) {
- const MethodDescriptor* result = underlay_->FindMethodByName(name);
- if (result != NULL) return result;
- }
- if (TryFindSymbolInFallbackDatabase(name)) {
- Symbol result = tables_->FindSymbolOfType(name, Symbol::METHOD);
- if (!result.IsNull()) return result.method_descriptor;
- }
- return NULL;
+ Symbol result = tables_->FindByNameHelper(this, name);
+ return (result.type == Symbol::METHOD) ? result.method_descriptor : NULL;
}
const FieldDescriptor* DescriptorPool::FindExtensionByNumber(
@@ -844,6 +885,30 @@ Descriptor::FindFieldByNumber(int key) const {
}
const FieldDescriptor*
+Descriptor::FindFieldByLowercaseName(const string& key) const {
+ MutexLockMaybe lock(file()->pool()->mutex_);
+ const FieldDescriptor* result =
+ file()->pool()->tables_->FindFieldByLowercaseName(this, key);
+ if (result == NULL || result->is_extension()) {
+ return NULL;
+ } else {
+ return result;
+ }
+}
+
+const FieldDescriptor*
+Descriptor::FindFieldByCamelcaseName(const string& key) const {
+ MutexLockMaybe lock(file()->pool()->mutex_);
+ const FieldDescriptor* result =
+ file()->pool()->tables_->FindFieldByCamelcaseName(this, key);
+ if (result == NULL || result->is_extension()) {
+ return NULL;
+ } else {
+ return result;
+ }
+}
+
+const FieldDescriptor*
Descriptor::FindFieldByName(const string& key) const {
MutexLockMaybe lock(file()->pool()->mutex_);
Symbol result =
@@ -867,6 +932,30 @@ Descriptor::FindExtensionByName(const string& key) const {
}
}
+const FieldDescriptor*
+Descriptor::FindExtensionByLowercaseName(const string& key) const {
+ MutexLockMaybe lock(file()->pool()->mutex_);
+ const FieldDescriptor* result =
+ file()->pool()->tables_->FindFieldByLowercaseName(this, key);
+ if (result == NULL || !result->is_extension()) {
+ return NULL;
+ } else {
+ return result;
+ }
+}
+
+const FieldDescriptor*
+Descriptor::FindExtensionByCamelcaseName(const string& key) const {
+ MutexLockMaybe lock(file()->pool()->mutex_);
+ const FieldDescriptor* result =
+ file()->pool()->tables_->FindFieldByCamelcaseName(this, key);
+ if (result == NULL || !result->is_extension()) {
+ return NULL;
+ } else {
+ return result;
+ }
+}
+
const Descriptor*
Descriptor::FindNestedTypeByName(const string& key) const {
MutexLockMaybe lock(file()->pool()->mutex_);
@@ -995,6 +1084,30 @@ FileDescriptor::FindExtensionByName(const string& key) const {
}
}
+const FieldDescriptor*
+FileDescriptor::FindExtensionByLowercaseName(const string& key) const {
+ MutexLockMaybe lock(pool()->mutex_);
+ const FieldDescriptor* result =
+ pool()->tables_->FindFieldByLowercaseName(this, key);
+ if (result == NULL || !result->is_extension()) {
+ return NULL;
+ } else {
+ return result;
+ }
+}
+
+const FieldDescriptor*
+FileDescriptor::FindExtensionByCamelcaseName(const string& key) const {
+ MutexLockMaybe lock(pool()->mutex_);
+ const FieldDescriptor* result =
+ pool()->tables_->FindFieldByCamelcaseName(this, key);
+ if (result == NULL || !result->is_extension()) {
+ return NULL;
+ } else {
+ return result;
+ }
+}
+
bool Descriptor::IsExtensionNumber(int number) const {
// Linear search should be fine because we don't expect a message to have
// more than a couple extension ranges.
@@ -2504,6 +2617,22 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto,
result->number_ = proto.number();
result->is_extension_ = is_extension;
+ // If .proto files follow the style guide then the name should already be
+ // lower-cased. If that's the case we can just reuse the string we already
+ // allocated rather than allocate a new one.
+ string lowercase_name(proto.name());
+ LowerString(&lowercase_name);
+ if (lowercase_name == proto.name()) {
+ result->lowercase_name_ = result->name_;
+ } else {
+ result->lowercase_name_ = tables_->AllocateString(lowercase_name);
+ }
+
+ // Don't bother with the above optimization for camel-case names since
+ // .proto files that follow the guide shouldn't be using names in this
+ // format, so the optimization wouldn't help much.
+ result->camelcase_name_ = tables_->AllocateString(ToCamelCase(proto.name()));
+
// Some compilers do not allow static_cast directly between two enum types,
// so we must cast to int first.
result->type_ = static_cast<FieldDescriptor::Type>(
@@ -3042,6 +3171,9 @@ void DescriptorBuilder::CrossLinkField(
conflicting_field->name()));
}
}
+
+ // Add the field to the lowercase-name and camelcase-name tables.
+ tables_->AddFieldByStylizedNames(field);
}
void DescriptorBuilder::CrossLinkEnum(
@@ -3136,6 +3268,20 @@ void DescriptorBuilder::ValidateFieldOptions(FieldDescriptor* field,
ValidateMapKey(field, proto);
}
+ // Only repeated primitive fields may be packed.
+ if (field->options().packed()) {
+ if (!field->is_repeated() ||
+ field->type() == FieldDescriptor::TYPE_STRING ||
+ field->type() == FieldDescriptor::TYPE_GROUP ||
+ field->type() == FieldDescriptor::TYPE_MESSAGE ||
+ field->type() == FieldDescriptor::TYPE_BYTES) {
+ AddError(
+ field->full_name(), proto,
+ DescriptorPool::ErrorCollector::TYPE,
+ "[packed = true] can only be specified for repeated primitive fields.");
+ }
+ }
+
// Note: Default instance may not yet be initialized here, so we have to
// avoid reading from it.
if (field->containing_type_ != NULL &&
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h
index 6d496e99..918aafbc 100644
--- a/src/google/protobuf/descriptor.h
+++ b/src/google/protobuf/descriptor.h
@@ -156,6 +156,19 @@ class LIBPROTOBUF_EXPORT Descriptor {
// Looks up a field by name. Returns NULL if no such field exists.
const FieldDescriptor* FindFieldByName(const string& name) const;
+ // Looks up a field by lowercased name (as returned by lowercase_name()).
+ // This lookup may be ambiguous if multiple field names differ only by case,
+ // in which case the field returned is chosen arbitrarily from the matches.
+ const FieldDescriptor* FindFieldByLowercaseName(
+ const string& lowercase_name) const;
+
+ // Looks up a field by camel-case name (as returned by camelcase_name()).
+ // This lookup may be ambiguous if multiple field names differ in a way that
+ // leads them to have identical camel-case names, in which case the field
+ // returned is chosen arbitrarily from the matches.
+ const FieldDescriptor* FindFieldByCamelcaseName(
+ const string& camelcase_name) const;
+
// Nested type stuff -----------------------------------------------
// The number of nested types in this message type.
@@ -213,6 +226,14 @@ class LIBPROTOBUF_EXPORT Descriptor {
// defined within this message type's scope.
const FieldDescriptor* FindExtensionByName(const string& name) const;
+ // Similar to FindFieldByLowercaseName(), but finds extensions defined within
+ // this message type's scope.
+ const FieldDescriptor* FindExtensionByLowercaseName(const string& name) const;
+
+ // Similar to FindFieldByCamelcaseName(), but finds extensions defined within
+ // this message type's scope.
+ const FieldDescriptor* FindExtensionByCamelcaseName(const string& name) const;
+
private:
typedef MessageOptions OptionsType;
@@ -336,6 +357,25 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
bool is_extension() const; // Is this an extension field?
int number() const; // Declared tag number.
+ // Same as name() except converted to lower-case. This (and especially the
+ // FindFieldByLowercaseName() method) can be useful when parsing formats
+ // which prefer to use lowercase naming style. (Although, technically
+ // field names should be lowercased anyway according to the protobuf style
+ // guide, so this only makes a difference when dealing with old .proto files
+ // which do not follow the guide.)
+ const string& lowercase_name() const;
+
+ // Same as name() except converted to camel-case. In this conversion, any
+ // time an underscore appears in the name, it is removed and the next
+ // letter is capitalized. Furthermore, the first letter of the name is
+ // lower-cased. Examples:
+ // FooBar -> fooBar
+ // foo_bar -> fooBar
+ // fooBar -> fooBar
+ // This (and especially the FindFieldByCamelcaseName() method) can be useful
+ // when parsing formats which prefer to use camel-case naming style.
+ const string& camelcase_name() const;
+
Type type() const; // Declared type of this field.
CppType cpp_type() const; // C++ type of this field.
Label label() const; // optional/required/repeated
@@ -431,6 +471,8 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
const string* name_;
const string* full_name_;
+ const string* lowercase_name_;
+ const string* camelcase_name_;
const FileDescriptor* file_;
int number_;
Type type_;
@@ -773,6 +815,12 @@ class LIBPROTOBUF_EXPORT FileDescriptor {
const ServiceDescriptor* FindServiceByName(const string& name) const;
// Find a top-level extension definition by name. Returns NULL if not found.
const FieldDescriptor* FindExtensionByName(const string& name) const;
+ // Similar to FindExtensionByName(), but searches by lowercased-name. See
+ // Descriptor::FindFieldByLowercaseName().
+ const FieldDescriptor* FindExtensionByLowercaseName(const string& name) const;
+ // Similar to FindExtensionByName(), but searches by camelcased-name. See
+ // Descriptor::FindFieldByCamelcaseName().
+ const FieldDescriptor* FindExtensionByCamelcaseName(const string& name) const;
// See Descriptor::CopyTo().
void CopyTo(FileDescriptorProto* proto) const;
@@ -1084,6 +1132,8 @@ PROTOBUF_DEFINE_OPTIONS_ACCESSOR(Descriptor, MessageOptions);
PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, name)
PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, full_name)
+PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, lowercase_name)
+PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, camelcase_name)
PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, file, const FileDescriptor*)
PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, number, int)
PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, is_extension, bool)
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index ceb99bf1..0df3f3bd 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -301,8 +301,9 @@ void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescr
MessageOptions_descriptor_, MessageOptions::default_instance_);
FieldOptions_descriptor_ = file->message_type(10);
FieldOptions::default_instance_ = new FieldOptions();
- static const int FieldOptions_offsets_[3] = {
+ static const int FieldOptions_offsets_[4] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, ctype_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, packed_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, experimental_map_key_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, uninterpreted_option_),
};
@@ -519,30 +520,30 @@ void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto() {
"\n\016MessageOptions\022&\n\027message_set_wire_for"
"mat\030\001 \001(\010:\005false\022C\n\024uninterpreted_option"
"\030\347\007 \003(\0132$.google.protobuf.UninterpretedO"
- "ption*\t\010\350\007\020\200\200\200\200\002\"\325\001\n\014FieldOptions\0222\n\005cty"
+ "ption*\t\010\350\007\020\200\200\200\200\002\"\345\001\n\014FieldOptions\0222\n\005cty"
"pe\030\001 \001(\0162#.google.protobuf.FieldOptions."
- "CType\022\034\n\024experimental_map_key\030\t \001(\t\022C\n\024u"
- "ninterpreted_option\030\347\007 \003(\0132$.google.prot"
- "obuf.UninterpretedOption\"#\n\005CType\022\010\n\004COR"
- "D\020\001\022\020\n\014STRING_PIECE\020\002*\t\010\350\007\020\200\200\200\200\002\"]\n\013Enum"
- "Options\022C\n\024uninterpreted_option\030\347\007 \003(\0132$"
- ".google.protobuf.UninterpretedOption*\t\010\350"
- "\007\020\200\200\200\200\002\"b\n\020EnumValueOptions\022C\n\024uninterpr"
- "eted_option\030\347\007 \003(\0132$.google.protobuf.Uni"
- "nterpretedOption*\t\010\350\007\020\200\200\200\200\002\"`\n\016ServiceOp"
- "tions\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.g"
- "oogle.protobuf.UninterpretedOption*\t\010\350\007\020"
- "\200\200\200\200\002\"_\n\rMethodOptions\022C\n\024uninterpreted_"
- "option\030\347\007 \003(\0132$.google.protobuf.Uninterp"
- "retedOption*\t\010\350\007\020\200\200\200\200\002\"\205\002\n\023Uninterpreted"
- "Option\022;\n\004name\030\002 \003(\0132-.google.protobuf.U"
- "ninterpretedOption.NamePart\022\030\n\020identifie"
- "r_value\030\003 \001(\t\022\032\n\022positive_int_value\030\004 \001("
- "\004\022\032\n\022negative_int_value\030\005 \001(\003\022\024\n\014double_"
- "value\030\006 \001(\001\022\024\n\014string_value\030\007 \001(\014\0323\n\010Nam"
- "ePart\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_extension"
- "\030\002 \002(\010B)\n\023com.google.protobufB\020Descripto"
- "rProtosH\001", 3449,
+ "CType\022\016\n\006packed\030\002 \001(\010\022\034\n\024experimental_ma"
+ "p_key\030\t \001(\t\022C\n\024uninterpreted_option\030\347\007 \003"
+ "(\0132$.google.protobuf.UninterpretedOption"
+ "\"#\n\005CType\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002*\t\010"
+ "\350\007\020\200\200\200\200\002\"]\n\013EnumOptions\022C\n\024uninterpreted"
+ "_option\030\347\007 \003(\0132$.google.protobuf.Uninter"
+ "pretedOption*\t\010\350\007\020\200\200\200\200\002\"b\n\020EnumValueOpti"
+ "ons\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.goo"
+ "gle.protobuf.UninterpretedOption*\t\010\350\007\020\200\200"
+ "\200\200\002\"`\n\016ServiceOptions\022C\n\024uninterpreted_o"
+ "ption\030\347\007 \003(\0132$.google.protobuf.Uninterpr"
+ "etedOption*\t\010\350\007\020\200\200\200\200\002\"_\n\rMethodOptions\022C"
+ "\n\024uninterpreted_option\030\347\007 \003(\0132$.google.p"
+ "rotobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\205"
+ "\002\n\023UninterpretedOption\022;\n\004name\030\002 \003(\0132-.g"
+ "oogle.protobuf.UninterpretedOption.NameP"
+ "art\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022positiv"
+ "e_int_value\030\004 \001(\004\022\032\n\022negative_int_value\030"
+ "\005 \001(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014string_va"
+ "lue\030\007 \001(\014\0323\n\010NamePart\022\021\n\tname_part\030\001 \002(\t"
+ "\022\024\n\014is_extension\030\002 \002(\010B)\n\023com.google.pro"
+ "tobufB\020DescriptorProtosH\001", 3465,
&protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescriptors);
}
@@ -639,7 +640,7 @@ bool FileDescriptorSet::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
// repeated .google.protobuf.FileDescriptorProto file = 1;
- for (int i = 0; i < file_.size(); i++) {
+ for (int i = 0; i < this->file_size(); i++) {
DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(1, this->file(i), output));
}
@@ -655,8 +656,8 @@ int FileDescriptorSet::ByteSize() const {
int total_size = 0;
// repeated .google.protobuf.FileDescriptorProto file = 1;
- total_size += 1 * file_size();
- for (int i = 0; i < file_size(); i++) {
+ total_size += 1 * this->file_size();
+ for (int i = 0; i < this->file_size(); i++) {
total_size +=
::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
this->file(i));
@@ -954,27 +955,27 @@ bool FileDescriptorProto::SerializeWithCachedSizes(
}
// repeated string dependency = 3;
- for (int i = 0; i < dependency_.size(); i++) {
+ for (int i = 0; i < this->dependency_size(); i++) {
DO_(::google::protobuf::internal::WireFormat::WriteString(3, this->dependency(i), output));
}
// repeated .google.protobuf.DescriptorProto message_type = 4;
- for (int i = 0; i < message_type_.size(); i++) {
+ for (int i = 0; i < this->message_type_size(); i++) {
DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(4, this->message_type(i), output));
}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
- for (int i = 0; i < enum_type_.size(); i++) {
+ for (int i = 0; i < this->enum_type_size(); i++) {
DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(5, this->enum_type(i), output));
}
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
- for (int i = 0; i < service_.size(); i++) {
+ for (int i = 0; i < this->service_size(); i++) {
DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(6, this->service(i), output));
}
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
- for (int i = 0; i < extension_.size(); i++) {
+ for (int i = 0; i < this->extension_size(); i++) {
DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(7, this->extension(i), output));
}
@@ -1016,39 +1017,39 @@ int FileDescriptorProto::ByteSize() const {
}
// repeated string dependency = 3;
- total_size += 1 * dependency_size();
- for (int i = 0; i < dependency_size(); i++) {
+ total_size += 1 * this->dependency_size();
+ for (int i = 0; i < this->dependency_size(); i++) {
total_size += ::google::protobuf::internal::WireFormat::StringSize(
this->dependency(i));
}
// repeated .google.protobuf.DescriptorProto message_type = 4;
- total_size += 1 * message_type_size();
- for (int i = 0; i < message_type_size(); i++) {
+ total_size += 1 * this->message_type_size();
+ for (int i = 0; i < this->message_type_size(); i++) {
total_size +=
::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
this->message_type(i));
}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
- total_size += 1 * enum_type_size();
- for (int i = 0; i < enum_type_size(); i++) {
+ total_size += 1 * this->enum_type_size();
+ for (int i = 0; i < this->enum_type_size(); i++) {
total_size +=
::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
this->enum_type(i));
}
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
- total_size += 1 * service_size();
- for (int i = 0; i < service_size(); i++) {
+ total_size += 1 * this->service_size();
+ for (int i = 0; i < this->service_size(); i++) {
total_size +=
::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
this->service(i));
}
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
- total_size += 1 * extension_size();
- for (int i = 0; i < extension_size(); i++) {
+ total_size += 1 * this->extension_size();
+ for (int i = 0; i < this->extension_size(); i++) {
total_size +=
::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
this->extension(i));
@@ -1564,27 +1565,27 @@ bool DescriptorProto::SerializeWithCachedSizes(
}
// repeated .google.protobuf.FieldDescriptorProto field = 2;
- for (int i = 0; i < field_.size(); i++) {
+ for (int i = 0; i < this->field_size(); i++) {
DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(2, this->field(i), output));
}
// repeated .google.protobuf.DescriptorProto nested_type = 3;
- for (int i = 0; i < nested_type_.size(); i++) {
+ for (int i = 0; i < this->nested_type_size(); i++) {
DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(3, this->nested_type(i), output));
}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
- for (int i = 0; i < enum_type_.size(); i++) {
+ for (int i = 0; i < this->enum_type_size(); i++) {
DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(4, this->enum_type(i), output));
}
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
- for (int i = 0; i < extension_range_.size(); i++) {
+ for (int i = 0; i < this->extension_range_size(); i++) {
DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(5, this->extension_range(i), output));
}
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
- for (int i = 0; i < extension_.size(); i++) {
+ for (int i = 0; i < this->extension_size(); i++) {
DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(6, this->extension(i), output));
}
@@ -1620,40 +1621,40 @@ int DescriptorProto::ByteSize() const {
}
// repeated .google.protobuf.FieldDescriptorProto field = 2;
- total_size += 1 * field_size();
- for (int i = 0; i < field_size(); i++) {
+ total_size += 1 * this->field_size();
+ for (int i = 0; i < this->field_size(); i++) {
total_size +=
::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
this->field(i));
}
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
- total_size += 1 * extension_size();
- for (int i = 0; i < extension_size(); i++) {
+ total_size += 1 * this->extension_size();
+ for (int i = 0; i < this->extension_size(); i++) {
total_size +=
::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
this->extension(i));
}
// repeated .google.protobuf.DescriptorProto nested_type = 3;
- total_size += 1 * nested_type_size();
- for (int i = 0; i < nested_type_size(); i++) {
+ total_size += 1 * this->nested_type_size();
+ for (int i = 0; i < this->nested_type_size(); i++) {
total_size +=
::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
this->nested_type(i));
}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
- total_size += 1 * enum_type_size();
- for (int i = 0; i < enum_type_size(); i++) {
+ total_size += 1 * this->enum_type_size();
+ for (int i = 0; i < this->enum_type_size(); i++) {
total_size +=
::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
this->enum_type(i));
}
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
- total_size += 1 * extension_range_size();
- for (int i = 0; i < extension_range_size(); i++) {
+ total_size += 1 * this->extension_range_size();
+ for (int i = 0; i < this->extension_range_size(); i++) {
total_size +=
::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
this->extension_range(i));
@@ -2407,7 +2408,7 @@ bool EnumDescriptorProto::SerializeWithCachedSizes(
}
// repeated .google.protobuf.EnumValueDescriptorProto value = 2;
- for (int i = 0; i < value_.size(); i++) {
+ for (int i = 0; i < this->value_size(); i++) {
DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(2, this->value(i), output));
}
@@ -2443,8 +2444,8 @@ int EnumDescriptorProto::ByteSize() const {
}
// repeated .google.protobuf.EnumValueDescriptorProto value = 2;
- total_size += 1 * value_size();
- for (int i = 0; i < value_size(); i++) {
+ total_size += 1 * this->value_size();
+ for (int i = 0; i < this->value_size(); i++) {
total_size +=
::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
this->value(i));
@@ -2919,7 +2920,7 @@ bool ServiceDescriptorProto::SerializeWithCachedSizes(
}
// repeated .google.protobuf.MethodDescriptorProto method = 2;
- for (int i = 0; i < method_.size(); i++) {
+ for (int i = 0; i < this->method_size(); i++) {
DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(2, this->method(i), output));
}
@@ -2955,8 +2956,8 @@ int ServiceDescriptorProto::ByteSize() const {
}
// repeated .google.protobuf.MethodDescriptorProto method = 2;
- total_size += 1 * method_size();
- for (int i = 0; i < method_size(); i++) {
+ total_size += 1 * this->method_size();
+ for (int i = 0; i < this->method_size(); i++) {
total_size +=
::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
this->method(i));
@@ -3561,7 +3562,7 @@ bool FileOptions::SerializeWithCachedSizes(
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- for (int i = 0; i < uninterpreted_option_.size(); i++) {
+ for (int i = 0; i < this->uninterpreted_option_size(); i++) {
DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output));
}
@@ -3606,8 +3607,8 @@ int FileOptions::ByteSize() const {
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- total_size += 2 * uninterpreted_option_size();
- for (int i = 0; i < uninterpreted_option_size(); i++) {
+ total_size += 2 * this->uninterpreted_option_size();
+ for (int i = 0; i < this->uninterpreted_option_size(); i++) {
total_size +=
::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
this->uninterpreted_option(i));
@@ -3821,7 +3822,7 @@ bool MessageOptions::SerializeWithCachedSizes(
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- for (int i = 0; i < uninterpreted_option_.size(); i++) {
+ for (int i = 0; i < this->uninterpreted_option_size(); i++) {
DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output));
}
@@ -3848,8 +3849,8 @@ int MessageOptions::ByteSize() const {
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- total_size += 2 * uninterpreted_option_size();
- for (int i = 0; i < uninterpreted_option_size(); i++) {
+ total_size += 2 * this->uninterpreted_option_size();
+ for (int i = 0; i < this->uninterpreted_option_size(); i++) {
total_size +=
::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
this->uninterpreted_option(i));
@@ -3954,6 +3955,7 @@ const FieldOptions_CType FieldOptions::CType_MIN;
const FieldOptions_CType FieldOptions::CType_MAX;
#endif // _MSC_VER
+
const ::std::string FieldOptions::_default_experimental_map_key_;
FieldOptions::FieldOptions()
@@ -3963,6 +3965,7 @@ FieldOptions::FieldOptions()
::google::protobuf::MessageFactory::generated_factory()),
_cached_size_(0),
ctype_(1),
+ packed_(false),
experimental_map_key_(const_cast< ::std::string*>(&_default_experimental_map_key_)) {
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -3976,6 +3979,7 @@ FieldOptions::FieldOptions(const FieldOptions& from)
::google::protobuf::MessageFactory::generated_factory()),
_cached_size_(0),
ctype_(1),
+ packed_(false),
experimental_map_key_(const_cast< ::std::string*>(&_default_experimental_map_key_)) {
::memset(_has_bits_, 0, sizeof(_has_bits_));
MergeFrom(from);
@@ -4009,7 +4013,8 @@ void FieldOptions::Clear() {
_extensions_.Clear();
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
ctype_ = 1;
- if (_has_bit(1)) {
+ packed_ = false;
+ if (_has_bit(2)) {
if (experimental_map_key_ != &_default_experimental_map_key_) {
experimental_map_key_->clear();
}
@@ -4039,6 +4044,20 @@ bool FieldOptions::MergePartialFromCodedStream(
} else {
mutable_unknown_fields()->AddField(1)->add_varint(value);
}
+ if (input->ExpectTag(16)) goto parse_packed;
+ break;
+ }
+
+ // optional bool packed = 2;
+ case 2: {
+ if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
+ ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) {
+ goto handle_uninterpreted;
+ }
+ parse_packed:
+ DO_(::google::protobuf::internal::WireFormat::ReadBool(
+ input, &packed_));
+ _set_bit(1);
if (input->ExpectTag(74)) goto parse_experimental_map_key;
break;
}
@@ -4097,13 +4116,18 @@ bool FieldOptions::SerializeWithCachedSizes(
DO_(::google::protobuf::internal::WireFormat::WriteEnum(1, this->ctype(), output));
}
- // optional string experimental_map_key = 9;
+ // optional bool packed = 2;
if (_has_bit(1)) {
+ DO_(::google::protobuf::internal::WireFormat::WriteBool(2, this->packed(), output));
+ }
+
+ // optional string experimental_map_key = 9;
+ if (_has_bit(2)) {
DO_(::google::protobuf::internal::WireFormat::WriteString(9, this->experimental_map_key(), output));
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- for (int i = 0; i < uninterpreted_option_.size(); i++) {
+ for (int i = 0; i < this->uninterpreted_option_size(); i++) {
DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output));
}
@@ -4129,6 +4153,11 @@ int FieldOptions::ByteSize() const {
::google::protobuf::internal::WireFormat::EnumSize(this->ctype());
}
+ // optional bool packed = 2;
+ if (has_packed()) {
+ total_size += 1 + 1;
+ }
+
// optional string experimental_map_key = 9;
if (has_experimental_map_key()) {
total_size += 1 +
@@ -4137,8 +4166,8 @@ int FieldOptions::ByteSize() const {
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- total_size += 2 * uninterpreted_option_size();
- for (int i = 0; i < uninterpreted_option_size(); i++) {
+ total_size += 2 * this->uninterpreted_option_size();
+ for (int i = 0; i < this->uninterpreted_option_size(); i++) {
total_size +=
::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
this->uninterpreted_option(i));
@@ -4175,6 +4204,9 @@ void FieldOptions::MergeFrom(const FieldOptions& from) {
set_ctype(from.ctype());
}
if (from._has_bit(1)) {
+ set_packed(from.packed());
+ }
+ if (from._has_bit(2)) {
set_experimental_map_key(from.experimental_map_key());
}
}
@@ -4197,6 +4229,7 @@ void FieldOptions::CopyFrom(const FieldOptions& from) {
void FieldOptions::Swap(FieldOptions* other) {
if (other != this) {
std::swap(ctype_, other->ctype_);
+ std::swap(packed_, other->packed_);
std::swap(experimental_map_key_, other->experimental_map_key_);
uninterpreted_option_.Swap(&other->uninterpreted_option_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
@@ -4320,7 +4353,7 @@ bool EnumOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- for (int i = 0; i < uninterpreted_option_.size(); i++) {
+ for (int i = 0; i < this->uninterpreted_option_size(); i++) {
DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output));
}
@@ -4340,8 +4373,8 @@ int EnumOptions::ByteSize() const {
int total_size = 0;
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- total_size += 2 * uninterpreted_option_size();
- for (int i = 0; i < uninterpreted_option_size(); i++) {
+ total_size += 2 * this->uninterpreted_option_size();
+ for (int i = 0; i < this->uninterpreted_option_size(); i++) {
total_size +=
::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
this->uninterpreted_option(i));
@@ -4513,7 +4546,7 @@ bool EnumValueOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- for (int i = 0; i < uninterpreted_option_.size(); i++) {
+ for (int i = 0; i < this->uninterpreted_option_size(); i++) {
DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output));
}
@@ -4533,8 +4566,8 @@ int EnumValueOptions::ByteSize() const {
int total_size = 0;
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- total_size += 2 * uninterpreted_option_size();
- for (int i = 0; i < uninterpreted_option_size(); i++) {
+ total_size += 2 * this->uninterpreted_option_size();
+ for (int i = 0; i < this->uninterpreted_option_size(); i++) {
total_size +=
::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
this->uninterpreted_option(i));
@@ -4706,7 +4739,7 @@ bool ServiceOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- for (int i = 0; i < uninterpreted_option_.size(); i++) {
+ for (int i = 0; i < this->uninterpreted_option_size(); i++) {
DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output));
}
@@ -4726,8 +4759,8 @@ int ServiceOptions::ByteSize() const {
int total_size = 0;
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- total_size += 2 * uninterpreted_option_size();
- for (int i = 0; i < uninterpreted_option_size(); i++) {
+ total_size += 2 * this->uninterpreted_option_size();
+ for (int i = 0; i < this->uninterpreted_option_size(); i++) {
total_size +=
::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
this->uninterpreted_option(i));
@@ -4899,7 +4932,7 @@ bool MethodOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- for (int i = 0; i < uninterpreted_option_.size(); i++) {
+ for (int i = 0; i < this->uninterpreted_option_size(); i++) {
DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output));
}
@@ -4919,8 +4952,8 @@ int MethodOptions::ByteSize() const {
int total_size = 0;
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- total_size += 2 * uninterpreted_option_size();
- for (int i = 0; i < uninterpreted_option_size(); i++) {
+ total_size += 2 * this->uninterpreted_option_size();
+ for (int i = 0; i < this->uninterpreted_option_size(); i++) {
total_size +=
::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
this->uninterpreted_option(i));
@@ -5398,7 +5431,7 @@ bool UninterpretedOption::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
// repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
- for (int i = 0; i < name_.size(); i++) {
+ for (int i = 0; i < this->name_size(); i++) {
DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(2, this->name(i), output));
}
@@ -5472,8 +5505,8 @@ int UninterpretedOption::ByteSize() const {
}
// repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
- total_size += 1 * name_size();
- for (int i = 0; i < name_size(); i++) {
+ total_size += 1 * this->name_size();
+ for (int i = 0; i < this->name_size(); i++) {
total_size +=
::google::protobuf::internal::WireFormat::MessageSizeNoVirtual(
this->name(i));
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index 8fa51dd6..e5077aae 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -12,7 +12,7 @@
#error incompatible with your Protocol Buffer headers. Please update
#error your headers.
#endif
-#if 2000003 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#if 2000004 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers. Please
#error regenerate this file with a newer version of protoc.
@@ -1645,6 +1645,12 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
inline ::google::protobuf::FieldOptions_CType ctype() const;
inline void set_ctype(::google::protobuf::FieldOptions_CType value);
+ // optional bool packed = 2;
+ inline bool has_packed() const;
+ inline void clear_packed();
+ inline bool packed() const;
+ inline void set_packed(bool value);
+
// optional string experimental_map_key = 9;
inline bool has_experimental_map_key() const;
inline void clear_experimental_map_key();
@@ -1749,12 +1755,13 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
mutable int _cached_size_;
int ctype_;
+ bool packed_;
::std::string* experimental_map_key_;
static const ::std::string _default_experimental_map_key_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescriptors(
const ::google::protobuf::FileDescriptor* file);
- ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
+ ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32];
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
inline bool _has_bit(int index) const {
@@ -3908,35 +3915,51 @@ inline void FieldOptions::set_ctype(::google::protobuf::FieldOptions_CType value
ctype_ = value;
}
+// optional bool packed = 2;
+inline bool FieldOptions::has_packed() const {
+ return _has_bit(1);
+}
+inline void FieldOptions::clear_packed() {
+ packed_ = false;
+ _clear_bit(1);
+}
+inline bool FieldOptions::packed() const {
+ return packed_;
+}
+inline void FieldOptions::set_packed(bool value) {
+ _set_bit(1);
+ packed_ = value;
+}
+
// optional string experimental_map_key = 9;
inline bool FieldOptions::has_experimental_map_key() const {
- return _has_bit(1);
+ return _has_bit(2);
}
inline void FieldOptions::clear_experimental_map_key() {
if (experimental_map_key_ != &_default_experimental_map_key_) {
experimental_map_key_->clear();
}
- _clear_bit(1);
+ _clear_bit(2);
}
inline const ::std::string& FieldOptions::experimental_map_key() const {
return *experimental_map_key_;
}
inline void FieldOptions::set_experimental_map_key(const ::std::string& value) {
- _set_bit(1);
+ _set_bit(2);
if (experimental_map_key_ == &_default_experimental_map_key_) {
experimental_map_key_ = new ::std::string;
}
experimental_map_key_->assign(value);
}
inline void FieldOptions::set_experimental_map_key(const char* value) {
- _set_bit(1);
+ _set_bit(2);
if (experimental_map_key_ == &_default_experimental_map_key_) {
experimental_map_key_ = new ::std::string;
}
experimental_map_key_->assign(value);
}
inline ::std::string* FieldOptions::mutable_experimental_map_key() {
- _set_bit(1);
+ _set_bit(2);
if (experimental_map_key_ == &_default_experimental_map_key_) {
experimental_map_key_ = new ::std::string;
}
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index 9cdd61c5..e0e6f7f2 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -253,6 +253,7 @@ message FileOptions {
optional OptimizeMode optimize_for = 9 [default=CODE_SIZE];
+
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
@@ -299,6 +300,11 @@ message FieldOptions {
STRING_PIECE = 2;
}
+ // The packed option can be enabled for repeated primitive fields to enable
+ // a more efficient representation on the wire. Rather than repeatedly
+ // writing the tag and type for each element, the entire array is encoded as
+ // a single length-delimited blob.
+ optional bool packed = 2;
// EXPERIMENTAL. DO NOT USE.
// For "map" fields, the name of the field in the enclosed type that
diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
index f4e60b3a..5ffaea77 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -53,7 +53,8 @@
namespace google {
namespace protobuf {
-namespace GOOGLE_ANONYMOUS_NAMESPACE{
+// Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
+namespace descriptor_unittest {
// Some helpers to make assembling descriptors faster.
DescriptorProto* AddMessage(FileDescriptorProto* file, const string& name) {
@@ -631,6 +632,188 @@ TEST_F(DescriptorTest, FieldEnumType) {
// ===================================================================
+class StylizedFieldNamesTest : public testing::Test {
+ protected:
+ void SetUp() {
+ FileDescriptorProto file;
+ file.set_name("foo.proto");
+
+ AddExtensionRange(AddMessage(&file, "ExtendableMessage"), 1, 1000);
+
+ DescriptorProto* message = AddMessage(&file, "TestMessage");
+ AddField(message, "foo_foo", 1,
+ FieldDescriptorProto::LABEL_OPTIONAL,
+ FieldDescriptorProto::TYPE_INT32);
+ AddField(message, "FooBar", 2,
+ FieldDescriptorProto::LABEL_OPTIONAL,
+ FieldDescriptorProto::TYPE_INT32);
+ AddField(message, "fooBaz", 3,
+ FieldDescriptorProto::LABEL_OPTIONAL,
+ FieldDescriptorProto::TYPE_INT32);
+ AddField(message, "fooFoo", 4, // Camel-case conflict with foo_foo.
+ FieldDescriptorProto::LABEL_OPTIONAL,
+ FieldDescriptorProto::TYPE_INT32);
+ AddField(message, "foobar", 5, // Lower-case conflict with FooBar.
+ FieldDescriptorProto::LABEL_OPTIONAL,
+ FieldDescriptorProto::TYPE_INT32);
+
+ AddNestedExtension(message, "ExtendableMessage", "bar_foo", 1,
+ FieldDescriptorProto::LABEL_OPTIONAL,
+ FieldDescriptorProto::TYPE_INT32);
+ AddNestedExtension(message, "ExtendableMessage", "BarBar", 2,
+ FieldDescriptorProto::LABEL_OPTIONAL,
+ FieldDescriptorProto::TYPE_INT32);
+ AddNestedExtension(message, "ExtendableMessage", "BarBaz", 3,
+ FieldDescriptorProto::LABEL_OPTIONAL,
+ FieldDescriptorProto::TYPE_INT32);
+ AddNestedExtension(message, "ExtendableMessage", "barFoo", 4, // Conflict
+ FieldDescriptorProto::LABEL_OPTIONAL,
+ FieldDescriptorProto::TYPE_INT32);
+ AddNestedExtension(message, "ExtendableMessage", "barbar", 5, // Conflict
+ FieldDescriptorProto::LABEL_OPTIONAL,
+ FieldDescriptorProto::TYPE_INT32);
+
+ AddExtension(&file, "ExtendableMessage", "baz_foo", 11,
+ FieldDescriptorProto::LABEL_OPTIONAL,
+ FieldDescriptorProto::TYPE_INT32);
+ AddExtension(&file, "ExtendableMessage", "BazBar", 12,
+ FieldDescriptorProto::LABEL_OPTIONAL,
+ FieldDescriptorProto::TYPE_INT32);
+ AddExtension(&file, "ExtendableMessage", "BazBaz", 13,
+ FieldDescriptorProto::LABEL_OPTIONAL,
+ FieldDescriptorProto::TYPE_INT32);
+ AddExtension(&file, "ExtendableMessage", "bazFoo", 14, // Conflict
+ FieldDescriptorProto::LABEL_OPTIONAL,
+ FieldDescriptorProto::TYPE_INT32);
+ AddExtension(&file, "ExtendableMessage", "bazbar", 15, // Conflict
+ FieldDescriptorProto::LABEL_OPTIONAL,
+ FieldDescriptorProto::TYPE_INT32);
+
+ file_ = pool_.BuildFile(file);
+ ASSERT_TRUE(file_ != NULL);
+ ASSERT_EQ(2, file_->message_type_count());
+ message_ = file_->message_type(1);
+ ASSERT_EQ("TestMessage", message_->name());
+ ASSERT_EQ(5, message_->field_count());
+ ASSERT_EQ(5, message_->extension_count());
+ ASSERT_EQ(5, file_->extension_count());
+ }
+
+ DescriptorPool pool_;
+ const FileDescriptor* file_;
+ const Descriptor* message_;
+};
+
+TEST_F(StylizedFieldNamesTest, LowercaseName) {
+ EXPECT_EQ("foo_foo", message_->field(0)->lowercase_name());
+ EXPECT_EQ("foobar" , message_->field(1)->lowercase_name());
+ EXPECT_EQ("foobaz" , message_->field(2)->lowercase_name());
+ EXPECT_EQ("foofoo" , message_->field(3)->lowercase_name());
+ EXPECT_EQ("foobar" , message_->field(4)->lowercase_name());
+
+ EXPECT_EQ("bar_foo", message_->extension(0)->lowercase_name());
+ EXPECT_EQ("barbar" , message_->extension(1)->lowercase_name());
+ EXPECT_EQ("barbaz" , message_->extension(2)->lowercase_name());
+ EXPECT_EQ("barfoo" , message_->extension(3)->lowercase_name());
+ EXPECT_EQ("barbar" , message_->extension(4)->lowercase_name());
+
+ EXPECT_EQ("baz_foo", file_->extension(0)->lowercase_name());
+ EXPECT_EQ("bazbar" , file_->extension(1)->lowercase_name());
+ EXPECT_EQ("bazbaz" , file_->extension(2)->lowercase_name());
+ EXPECT_EQ("bazfoo" , file_->extension(3)->lowercase_name());
+ EXPECT_EQ("bazbar" , file_->extension(4)->lowercase_name());
+}
+
+TEST_F(StylizedFieldNamesTest, CamelcaseName) {
+ EXPECT_EQ("fooFoo", message_->field(0)->camelcase_name());
+ EXPECT_EQ("fooBar", message_->field(1)->camelcase_name());
+ EXPECT_EQ("fooBaz", message_->field(2)->camelcase_name());
+ EXPECT_EQ("fooFoo", message_->field(3)->camelcase_name());
+ EXPECT_EQ("foobar", message_->field(4)->camelcase_name());
+
+ EXPECT_EQ("barFoo", message_->extension(0)->camelcase_name());
+ EXPECT_EQ("barBar", message_->extension(1)->camelcase_name());
+ EXPECT_EQ("barBaz", message_->extension(2)->camelcase_name());
+ EXPECT_EQ("barFoo", message_->extension(3)->camelcase_name());
+ EXPECT_EQ("barbar", message_->extension(4)->camelcase_name());
+
+ EXPECT_EQ("bazFoo", file_->extension(0)->camelcase_name());
+ EXPECT_EQ("bazBar", file_->extension(1)->camelcase_name());
+ EXPECT_EQ("bazBaz", file_->extension(2)->camelcase_name());
+ EXPECT_EQ("bazFoo", file_->extension(3)->camelcase_name());
+ EXPECT_EQ("bazbar", file_->extension(4)->camelcase_name());
+}
+
+TEST_F(StylizedFieldNamesTest, FindByLowercaseName) {
+ EXPECT_EQ(message_->field(0),
+ message_->FindFieldByLowercaseName("foo_foo"));
+ EXPECT_EQ(message_->field(1),
+ message_->FindFieldByLowercaseName("foobar"));
+ EXPECT_EQ(message_->field(2),
+ message_->FindFieldByLowercaseName("foobaz"));
+ EXPECT_TRUE(message_->FindFieldByLowercaseName("FooBar") == NULL);
+ EXPECT_TRUE(message_->FindFieldByLowercaseName("fooBaz") == NULL);
+ EXPECT_TRUE(message_->FindFieldByLowercaseName("bar_foo") == NULL);
+ EXPECT_TRUE(message_->FindFieldByLowercaseName("nosuchfield") == NULL);
+
+ EXPECT_EQ(message_->extension(0),
+ message_->FindExtensionByLowercaseName("bar_foo"));
+ EXPECT_EQ(message_->extension(1),
+ message_->FindExtensionByLowercaseName("barbar"));
+ EXPECT_EQ(message_->extension(2),
+ message_->FindExtensionByLowercaseName("barbaz"));
+ EXPECT_TRUE(message_->FindExtensionByLowercaseName("BarBar") == NULL);
+ EXPECT_TRUE(message_->FindExtensionByLowercaseName("barBaz") == NULL);
+ EXPECT_TRUE(message_->FindExtensionByLowercaseName("foo_foo") == NULL);
+ EXPECT_TRUE(message_->FindExtensionByLowercaseName("nosuchfield") == NULL);
+
+ EXPECT_EQ(file_->extension(0),
+ file_->FindExtensionByLowercaseName("baz_foo"));
+ EXPECT_EQ(file_->extension(1),
+ file_->FindExtensionByLowercaseName("bazbar"));
+ EXPECT_EQ(file_->extension(2),
+ file_->FindExtensionByLowercaseName("bazbaz"));
+ EXPECT_TRUE(file_->FindExtensionByLowercaseName("BazBar") == NULL);
+ EXPECT_TRUE(file_->FindExtensionByLowercaseName("bazBaz") == NULL);
+ EXPECT_TRUE(file_->FindExtensionByLowercaseName("nosuchfield") == NULL);
+}
+
+TEST_F(StylizedFieldNamesTest, FindByCamelcaseName) {
+ EXPECT_EQ(message_->field(0),
+ message_->FindFieldByCamelcaseName("fooFoo"));
+ EXPECT_EQ(message_->field(1),
+ message_->FindFieldByCamelcaseName("fooBar"));
+ EXPECT_EQ(message_->field(2),
+ message_->FindFieldByCamelcaseName("fooBaz"));
+ EXPECT_TRUE(message_->FindFieldByCamelcaseName("foo_foo") == NULL);
+ EXPECT_TRUE(message_->FindFieldByCamelcaseName("FooBar") == NULL);
+ EXPECT_TRUE(message_->FindFieldByCamelcaseName("barFoo") == NULL);
+ EXPECT_TRUE(message_->FindFieldByCamelcaseName("nosuchfield") == NULL);
+
+ EXPECT_EQ(message_->extension(0),
+ message_->FindExtensionByCamelcaseName("barFoo"));
+ EXPECT_EQ(message_->extension(1),
+ message_->FindExtensionByCamelcaseName("barBar"));
+ EXPECT_EQ(message_->extension(2),
+ message_->FindExtensionByCamelcaseName("barBaz"));
+ EXPECT_TRUE(message_->FindExtensionByCamelcaseName("bar_foo") == NULL);
+ EXPECT_TRUE(message_->FindExtensionByCamelcaseName("BarBar") == NULL);
+ EXPECT_TRUE(message_->FindExtensionByCamelcaseName("fooFoo") == NULL);
+ EXPECT_TRUE(message_->FindExtensionByCamelcaseName("nosuchfield") == NULL);
+
+ EXPECT_EQ(file_->extension(0),
+ file_->FindExtensionByCamelcaseName("bazFoo"));
+ EXPECT_EQ(file_->extension(1),
+ file_->FindExtensionByCamelcaseName("bazBar"));
+ EXPECT_EQ(file_->extension(2),
+ file_->FindExtensionByCamelcaseName("bazBaz"));
+ EXPECT_TRUE(file_->FindExtensionByCamelcaseName("baz_foo") == NULL);
+ EXPECT_TRUE(file_->FindExtensionByCamelcaseName("BazBar") == NULL);
+ EXPECT_TRUE(file_->FindExtensionByCamelcaseName("nosuchfield") == NULL);
+}
+
+// ===================================================================
+
// Test enum descriptors.
class EnumDescriptorTest : public testing::Test {
protected:
@@ -2457,6 +2640,36 @@ TEST_F(ValidationErrorTest, OutputTypeNotAMessage) {
"foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not a message type.\n");
}
+TEST_F(ValidationErrorTest, IllegalPackedField) {
+ BuildFileWithErrors(
+ "name: \"foo.proto\" "
+ "message_type {\n"
+ " name: \"Foo\""
+ " field { name:\"packed_string\" number:1 label:LABEL_REPEATED "
+ " type:TYPE_STRING "
+ " options { uninterpreted_option {"
+ " name { name_part: \"packed\" is_extension: false }"
+ " identifier_value: \"true\" }}}\n"
+ " field { name:\"packed_message\" number:3 label:LABEL_REPEATED "
+ " type_name: \"Foo\""
+ " options { uninterpreted_option {"
+ " name { name_part: \"packed\" is_extension: false }"
+ " identifier_value: \"true\" }}}\n"
+ " field { name:\"optional_int32\" number: 4 label: LABEL_OPTIONAL "
+ " type:TYPE_INT32 "
+ " options { uninterpreted_option {"
+ " name { name_part: \"packed\" is_extension: false }"
+ " identifier_value: \"true\" }}}\n"
+ "}",
+
+ "foo.proto: Foo.packed_string: TYPE: [packed = true] can only be "
+ "specified for repeated primitive fields.\n"
+ "foo.proto: Foo.packed_message: TYPE: [packed = true] can only be "
+ "specified for repeated primitive fields.\n"
+ "foo.proto: Foo.optional_int32: TYPE: [packed = true] can only be "
+ "specified for repeated primitive fields.\n"
+ );
+}
TEST_F(ValidationErrorTest, OptionWrongType) {
BuildFileWithErrors(
@@ -3255,6 +3468,34 @@ TEST_F(DatabaseBackedPoolTest, DoesntReloadKnownBadFiles) {
EXPECT_EQ("", error_collector.text_);
}
-} // anonymous namespace
+TEST_F(DatabaseBackedPoolTest, DoesntFallbackOnWrongType) {
+ // If a lookup finds a symbol of the wrong type (e.g. we pass a type name
+ // to FindFieldByName()), we should fail fast, without checking the fallback
+ // database.
+ CallCountingDatabase call_counter(&database_);
+ DescriptorPool pool(&call_counter);
+
+ const FileDescriptor* file = pool.FindFileByName("foo.proto");
+ ASSERT_TRUE(file != NULL);
+ const Descriptor* foo = pool.FindMessageTypeByName("Foo");
+ ASSERT_TRUE(foo != NULL);
+ const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum");
+ ASSERT_TRUE(test_enum != NULL);
+
+ EXPECT_NE(0, call_counter.call_count_);
+ call_counter.Clear();
+
+ EXPECT_TRUE(pool.FindMessageTypeByName("TestEnum") == NULL);
+ EXPECT_TRUE(pool.FindFieldByName("Foo") == NULL);
+ EXPECT_TRUE(pool.FindExtensionByName("Foo") == NULL);
+ EXPECT_TRUE(pool.FindEnumTypeByName("Foo") == NULL);
+ EXPECT_TRUE(pool.FindEnumValueByName("Foo") == NULL);
+ EXPECT_TRUE(pool.FindServiceByName("Foo") == NULL);
+ EXPECT_TRUE(pool.FindMethodByName("Foo") == NULL);
+
+ EXPECT_EQ(0, call_counter.call_count_);
+}
+
+} // namespace descriptor_unittest
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/dynamic_message_unittest.cc b/src/google/protobuf/dynamic_message_unittest.cc
index 5f7af94e..41b89ab5 100644
--- a/src/google/protobuf/dynamic_message_unittest.cc
+++ b/src/google/protobuf/dynamic_message_unittest.cc
@@ -61,6 +61,8 @@ class DynamicMessageTest : public testing::Test {
const Message* prototype_;
const Descriptor* extensions_descriptor_;
const Message* extensions_prototype_;
+ const Descriptor* packed_descriptor_;
+ const Message* packed_prototype_;
DynamicMessageTest(): factory_(&pool_) {}
@@ -87,6 +89,11 @@ class DynamicMessageTest : public testing::Test {
pool_.FindMessageTypeByName("protobuf_unittest.TestAllExtensions");
ASSERT_TRUE(extensions_descriptor_ != NULL);
extensions_prototype_ = factory_.GetPrototype(extensions_descriptor_);
+
+ packed_descriptor_ =
+ pool_.FindMessageTypeByName("protobuf_unittest.TestPackedTypes");
+ ASSERT_TRUE(packed_descriptor_ != NULL);
+ packed_prototype_ = factory_.GetPrototype(packed_descriptor_);
}
};
@@ -127,6 +134,15 @@ TEST_F(DynamicMessageTest, Extensions) {
reflection_tester.ExpectAllFieldsSetViaReflection(*message);
}
+TEST_F(DynamicMessageTest, PackedFields) {
+ // Check that packed fields work properly.
+ scoped_ptr<Message> message(packed_prototype_->New());
+ TestUtil::ReflectionTester reflection_tester(packed_descriptor_);
+
+ reflection_tester.SetPackedFieldsViaReflection(message.get());
+ reflection_tester.ExpectPackedFieldsSetViaReflection(*message);
+}
+
TEST_F(DynamicMessageTest, SpaceUsed) {
// Test that SpaceUsed() works properly
diff --git a/src/google/protobuf/extension_set_unittest.cc b/src/google/protobuf/extension_set_unittest.cc
index c3ac7ce7..631bbc43 100644
--- a/src/google/protobuf/extension_set_unittest.cc
+++ b/src/google/protobuf/extension_set_unittest.cc
@@ -179,6 +179,19 @@ TEST(ExtensionSetTest, Serialization) {
TestUtil::ExpectAllFieldsSet(destination);
}
+TEST(ExtensionSetTest, PackedSerialization) {
+ // Serialize as TestPackedExtensions and parse as TestPackedTypes to insure
+ // wire compatibility of extensions.
+ unittest::TestPackedExtensions source;
+ unittest::TestPackedTypes destination;
+ string data;
+
+ TestUtil::SetPackedExtensions(&source);
+ source.SerializeToString(&data);
+ EXPECT_TRUE(destination.ParseFromString(data));
+ TestUtil::ExpectPackedFieldsSet(destination);
+}
+
TEST(ExtensionSetTest, Parsing) {
// Serialize as TestAllTypes and parse as TestAllExtensions.
unittest::TestAllTypes source;
@@ -191,6 +204,18 @@ TEST(ExtensionSetTest, Parsing) {
TestUtil::ExpectAllExtensionsSet(destination);
}
+TEST(ExtensionSetTest, PackedParsing) {
+ // Serialize as TestPackedTypes and parse as TestPackedExtensions.
+ unittest::TestPackedTypes source;
+ unittest::TestPackedExtensions destination;
+ string data;
+
+ TestUtil::SetPackedFields(&source);
+ source.SerializeToString(&data);
+ EXPECT_TRUE(destination.ParseFromString(data));
+ TestUtil::ExpectPackedExtensionsSet(destination);
+}
+
TEST(ExtensionSetTest, IsInitialized) {
// Test that IsInitialized() returns false if required fields in nested
// extensions are missing.
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc
index 66f95906..a0f08571 100644
--- a/src/google/protobuf/io/coded_stream.cc
+++ b/src/google/protobuf/io/coded_stream.cc
@@ -207,6 +207,14 @@ bool CodedInputStream::Skip(int count) {
return input_->Skip(count);
}
+bool CodedInputStream::GetDirectBufferPointer(const void** data, int* size) {
+ if (buffer_size_ == 0 && !Refresh()) return false;
+
+ *data = buffer_;
+ *size = buffer_size_;
+ return true;
+}
+
bool CodedInputStream::ReadRaw(void* buffer, int size) {
while (buffer_size_ < size) {
// Reading past end of buffer. Copy what we have, then refresh.
@@ -515,6 +523,26 @@ CodedOutputStream::~CodedOutputStream() {
}
}
+bool CodedOutputStream::Skip(int count) {
+ if (count < 0) return false;
+
+ while (count > buffer_size_) {
+ count -= buffer_size_;
+ if (!Refresh()) return false;
+ }
+
+ Advance(count);
+ return true;
+}
+
+bool CodedOutputStream::GetDirectBufferPointer(void** data, int* size) {
+ if (buffer_size_ == 0 && !Refresh()) return false;
+
+ *data = buffer_;
+ *size = buffer_size_;
+ return true;
+}
+
bool CodedOutputStream::WriteRaw(const void* data, int size) {
while (buffer_size_ < size) {
memcpy(buffer_, data, buffer_size_);
diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
index a73ac0ba..8ebe4b35 100644
--- a/src/google/protobuf/io/coded_stream.h
+++ b/src/google/protobuf/io/coded_stream.h
@@ -149,6 +149,15 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// occurs.
bool Skip(int count);
+ // Sets *data to point directly at the unread part of the CodedInputStream's
+ // underlying buffer, and *size to the size of that buffer, but does not
+ // advance the stream's current position. This will always either produce
+ // a non-empty buffer or return false. If the caller consumes any of
+ // this data, it should then call Skip() to skip over the consumed bytes.
+ // This may be useful for implementing external fast parsing routines for
+ // types of data not covered by the CodedInputStream interface.
+ bool GetDirectBufferPointer(const void** data, int* size);
+
// Read raw bytes, copying them into the given buffer.
bool ReadRaw(void* buffer, int size);
@@ -381,6 +390,21 @@ class LIBPROTOBUF_EXPORT CodedOutputStream {
// ZeroCopyOutputStream immediately after the last byte written.
~CodedOutputStream();
+ // Skips a number of bytes, leaving the bytes unmodified in the underlying
+ // buffer. Returns false if an underlying write error occurs. This is
+ // mainly useful with GetDirectBufferPointer().
+ bool Skip(int count);
+
+ // Sets *data to point directly at the unwritten part of the
+ // CodedOutputStream's underlying buffer, and *size to the size of that
+ // buffer, but does not advance the stream's current position. This will
+ // always either produce a non-empty buffer or return false. If the caller
+ // writes any data to this buffer, it should then call Skip() to skip over
+ // the consumed bytes. This may be useful for implementing external fast
+ // serialization routines for types of data not covered by the
+ // CodedOutputStream interface.
+ bool GetDirectBufferPointer(void** data, int* size);
+
// Write raw bytes, copying them from the given buffer.
bool WriteRaw(const void* buffer, int size);
@@ -518,7 +542,7 @@ inline bool CodedInputStream::ExpectAtEnd() {
inline bool CodedOutputStream::WriteVarint32(uint32 value) {
if (value < 0x80 && buffer_size_ > 0) {
- *buffer_ = value;
+ *buffer_ = static_cast<uint8>(value);
Advance(1);
return true;
} else {
@@ -537,7 +561,7 @@ inline bool CodedOutputStream::WriteVarint32SignExtended(int32 value) {
inline bool CodedOutputStream::WriteTag(uint32 value) {
if (value < (1 << 7)) {
if (buffer_size_ != 0) {
- buffer_[0] = value;
+ buffer_[0] = static_cast<uint8>(value);
Advance(1);
return true;
}
diff --git a/src/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc
index 459b94a6..6a6eafe9 100644
--- a/src/google/protobuf/io/coded_stream_unittest.cc
+++ b/src/google/protobuf/io/coded_stream_unittest.cc
@@ -77,6 +77,9 @@ namespace {
// which failed will be printed. The case type must be printable using
// ostream::operator<<.
+// TODO(kenton): gTest now supports "parameterized tests" which would be
+// a better way to accomplish this. Rewrite when time permits.
+
#define TEST_1D(FIXTURE, NAME, CASES) \
class FIXTURE##_##NAME##_DD : public FIXTURE { \
protected: \
@@ -614,6 +617,73 @@ TEST_1D(CodedStreamTest, SkipInput, kBlockSizes) {
}
// -------------------------------------------------------------------
+// GetDirectBufferPointer
+
+TEST_F(CodedStreamTest, GetDirectBufferPointerInput) {
+ ArrayInputStream input(buffer_, sizeof(buffer_), 8);
+ CodedInputStream coded_input(&input);
+
+ const void* ptr;
+ int size;
+
+ EXPECT_TRUE(coded_input.GetDirectBufferPointer(&ptr, &size));
+ EXPECT_EQ(buffer_, ptr);
+ EXPECT_EQ(8, size);
+
+ // Peeking again should return the same pointer.
+ EXPECT_TRUE(coded_input.GetDirectBufferPointer(&ptr, &size));
+ EXPECT_EQ(buffer_, ptr);
+ EXPECT_EQ(8, size);
+
+ // Skip forward in the same buffer then peek again.
+ EXPECT_TRUE(coded_input.Skip(3));
+ EXPECT_TRUE(coded_input.GetDirectBufferPointer(&ptr, &size));
+ EXPECT_EQ(buffer_ + 3, ptr);
+ EXPECT_EQ(5, size);
+
+ // Skip to end of buffer and peek -- should get next buffer.
+ EXPECT_TRUE(coded_input.Skip(5));
+ EXPECT_TRUE(coded_input.GetDirectBufferPointer(&ptr, &size));
+ EXPECT_EQ(buffer_ + 8, ptr);
+ EXPECT_EQ(8, size);
+}
+
+TEST_F(CodedStreamTest, GetDirectBufferPointerOutput) {
+ ArrayOutputStream output(buffer_, sizeof(buffer_), 8);
+ CodedOutputStream coded_output(&output);
+
+ void* ptr;
+ int size;
+
+ EXPECT_TRUE(coded_output.GetDirectBufferPointer(&ptr, &size));
+ EXPECT_EQ(buffer_, ptr);
+ EXPECT_EQ(8, size);
+
+ // Peeking again should return the same pointer.
+ EXPECT_TRUE(coded_output.GetDirectBufferPointer(&ptr, &size));
+ EXPECT_EQ(buffer_, ptr);
+ EXPECT_EQ(8, size);
+
+ // Skip forward in the same buffer then peek again.
+ EXPECT_TRUE(coded_output.Skip(3));
+ EXPECT_TRUE(coded_output.GetDirectBufferPointer(&ptr, &size));
+ EXPECT_EQ(buffer_ + 3, ptr);
+ EXPECT_EQ(5, size);
+
+ // Skip to end of buffer and peek -- should get next buffer.
+ EXPECT_TRUE(coded_output.Skip(5));
+ EXPECT_TRUE(coded_output.GetDirectBufferPointer(&ptr, &size));
+ EXPECT_EQ(buffer_ + 8, ptr);
+ EXPECT_EQ(8, size);
+
+ // Skip over multiple buffers.
+ EXPECT_TRUE(coded_output.Skip(22));
+ EXPECT_TRUE(coded_output.GetDirectBufferPointer(&ptr, &size));
+ EXPECT_EQ(buffer_ + 30, ptr);
+ EXPECT_EQ(2, size);
+}
+
+// -------------------------------------------------------------------
// Limits
TEST_1D(CodedStreamTest, BasicLimit, kBlockSizes) {
diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc
index f6c932ff..097411cb 100644
--- a/src/google/protobuf/message.cc
+++ b/src/google/protobuf/message.cc
@@ -145,24 +145,42 @@ bool Message::ParsePartialFromZeroCopyStream(io::ZeroCopyInputStream* input) {
decoder.ConsumedEntireMessage();
}
+bool Message::ParseFromBoundedZeroCopyStream(
+ io::ZeroCopyInputStream* input, int size) {
+ io::CodedInputStream decoder(input);
+ decoder.PushLimit(size);
+ return ParseFromCodedStream(&decoder) &&
+ decoder.ConsumedEntireMessage() &&
+ decoder.BytesUntilLimit() == 0;
+}
+
+bool Message::ParsePartialFromBoundedZeroCopyStream(
+ io::ZeroCopyInputStream* input, int size) {
+ io::CodedInputStream decoder(input);
+ decoder.PushLimit(size);
+ return ParsePartialFromCodedStream(&decoder) &&
+ decoder.ConsumedEntireMessage() &&
+ decoder.BytesUntilLimit() == 0;
+}
+
bool Message::ParseFromString(const string& data) {
io::ArrayInputStream input(data.data(), data.size());
- return ParseFromZeroCopyStream(&input);
+ return ParseFromBoundedZeroCopyStream(&input, data.size());
}
bool Message::ParsePartialFromString(const string& data) {
io::ArrayInputStream input(data.data(), data.size());
- return ParsePartialFromZeroCopyStream(&input);
+ return ParsePartialFromBoundedZeroCopyStream(&input, data.size());
}
bool Message::ParseFromArray(const void* data, int size) {
io::ArrayInputStream input(data, size);
- return ParseFromZeroCopyStream(&input);
+ return ParseFromBoundedZeroCopyStream(&input, size);
}
bool Message::ParsePartialFromArray(const void* data, int size) {
io::ArrayInputStream input(data, size);
- return ParsePartialFromZeroCopyStream(&input);
+ return ParsePartialFromBoundedZeroCopyStream(&input, size);
}
bool Message::ParseFromFileDescriptor(int file_descriptor) {
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index d96fcc60..0674a12c 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -232,6 +232,14 @@ class LIBPROTOBUF_EXPORT Message {
// Like ParseFromZeroCopyStream(), but accepts messages that are missing
// required fields.
bool ParsePartialFromZeroCopyStream(io::ZeroCopyInputStream* input);
+ // Read a protocol buffer from the given zero-copy input stream, expecting
+ // the message to be exactly "size" bytes long. If successful, exactly
+ // this many bytes will have been consumed from the input.
+ bool ParseFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, int size);
+ // Like ParseFromBoundedZeroCopyStream(), but accepts messages that are
+ // missing required fields.
+ bool ParsePartialFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input,
+ int size);
// Parse a protocol buffer contained in a string.
bool ParseFromString(const string& data);
// Like ParseFromString(), but accepts messages that are missing
diff --git a/src/google/protobuf/message_unittest.cc b/src/google/protobuf/message_unittest.cc
index da99741b..46e68446 100644
--- a/src/google/protobuf/message_unittest.cc
+++ b/src/google/protobuf/message_unittest.cc
@@ -107,6 +107,19 @@ TEST(MessageTest, ParseFromFileDescriptor) {
EXPECT_GE(close(file), 0);
}
+TEST(MessageTest, ParsePackedFromFileDescriptor) {
+ string filename =
+ TestSourceDir() +
+ "/google/protobuf/testdata/golden_packed_fields_message";
+ int file = open(filename.c_str(), O_RDONLY | O_BINARY);
+
+ unittest::TestPackedTypes message;
+ EXPECT_TRUE(message.ParseFromFileDescriptor(file));
+ TestUtil::ExpectPackedFieldsSet(message);
+
+ EXPECT_GE(close(file), 0);
+}
+
TEST(MessageTest, ParseHelpers) {
// TODO(kenton): Test more helpers? They're all two-liners so it seems
// like a waste of time.
@@ -134,6 +147,25 @@ TEST(MessageTest, ParseHelpers) {
EXPECT_TRUE(stream.eof());
TestUtil::ExpectAllFieldsSet(message);
}
+
+ {
+ // Test ParseFromBoundedZeroCopyStream.
+ string data_with_junk(data);
+ data_with_junk.append("some junk on the end");
+ io::ArrayInputStream stream(data_with_junk.data(), data_with_junk.size());
+ protobuf_unittest::TestAllTypes message;
+ EXPECT_TRUE(message.ParseFromBoundedZeroCopyStream(&stream, data.size()));
+ TestUtil::ExpectAllFieldsSet(message);
+ }
+
+ {
+ // Test that ParseFromBoundedZeroCopyStream fails (but doesn't crash) if
+ // EOF is reached before the expected number of bytes.
+ io::ArrayInputStream stream(data.data(), data.size());
+ protobuf_unittest::TestAllTypes message;
+ EXPECT_FALSE(
+ message.ParseFromBoundedZeroCopyStream(&stream, data.size() + 1));
+ }
}
TEST(MessageTest, ParseFailsIfNotInitialized) {
diff --git a/src/google/protobuf/test_util.cc b/src/google/protobuf/test_util.cc
index 40120d95..c1e9fa78 100644
--- a/src/google/protobuf/test_util.cc
+++ b/src/google/protobuf/test_util.cc
@@ -636,6 +636,180 @@ void TestUtil::ExpectRepeatedFieldsModified(
}
+// -------------------------------------------------------------------
+
+void TestUtil::SetPackedFields(unittest::TestPackedTypes* message) {
+ message->add_packed_int32 (601);
+ message->add_packed_int64 (602);
+ message->add_packed_uint32 (603);
+ message->add_packed_uint64 (604);
+ message->add_packed_sint32 (605);
+ message->add_packed_sint64 (606);
+ message->add_packed_fixed32 (607);
+ message->add_packed_fixed64 (608);
+ message->add_packed_sfixed32(609);
+ message->add_packed_sfixed64(610);
+ message->add_packed_float (611);
+ message->add_packed_double (612);
+ message->add_packed_bool (true);
+ message->add_packed_enum (unittest::FOREIGN_BAR);
+ // add a second one of each field
+ message->add_packed_int32 (701);
+ message->add_packed_int64 (702);
+ message->add_packed_uint32 (703);
+ message->add_packed_uint64 (704);
+ message->add_packed_sint32 (705);
+ message->add_packed_sint64 (706);
+ message->add_packed_fixed32 (707);
+ message->add_packed_fixed64 (708);
+ message->add_packed_sfixed32(709);
+ message->add_packed_sfixed64(710);
+ message->add_packed_float (711);
+ message->add_packed_double (712);
+ message->add_packed_bool (false);
+ message->add_packed_enum (unittest::FOREIGN_BAZ);
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ModifyPackedFields(unittest::TestPackedTypes* message) {
+ message->set_packed_int32 (1, 801);
+ message->set_packed_int64 (1, 802);
+ message->set_packed_uint32 (1, 803);
+ message->set_packed_uint64 (1, 804);
+ message->set_packed_sint32 (1, 805);
+ message->set_packed_sint64 (1, 806);
+ message->set_packed_fixed32 (1, 807);
+ message->set_packed_fixed64 (1, 808);
+ message->set_packed_sfixed32(1, 809);
+ message->set_packed_sfixed64(1, 810);
+ message->set_packed_float (1, 811);
+ message->set_packed_double (1, 812);
+ message->set_packed_bool (1, true);
+ message->set_packed_enum (1, unittest::FOREIGN_FOO);
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ExpectPackedFieldsSet(const unittest::TestPackedTypes& message) {
+ ASSERT_EQ(2, message.packed_int32_size ());
+ ASSERT_EQ(2, message.packed_int64_size ());
+ ASSERT_EQ(2, message.packed_uint32_size ());
+ ASSERT_EQ(2, message.packed_uint64_size ());
+ ASSERT_EQ(2, message.packed_sint32_size ());
+ ASSERT_EQ(2, message.packed_sint64_size ());
+ ASSERT_EQ(2, message.packed_fixed32_size ());
+ ASSERT_EQ(2, message.packed_fixed64_size ());
+ ASSERT_EQ(2, message.packed_sfixed32_size());
+ ASSERT_EQ(2, message.packed_sfixed64_size());
+ ASSERT_EQ(2, message.packed_float_size ());
+ ASSERT_EQ(2, message.packed_double_size ());
+ ASSERT_EQ(2, message.packed_bool_size ());
+ ASSERT_EQ(2, message.packed_enum_size ());
+
+ EXPECT_EQ(601 , message.packed_int32 (0));
+ EXPECT_EQ(602 , message.packed_int64 (0));
+ EXPECT_EQ(603 , message.packed_uint32 (0));
+ EXPECT_EQ(604 , message.packed_uint64 (0));
+ EXPECT_EQ(605 , message.packed_sint32 (0));
+ EXPECT_EQ(606 , message.packed_sint64 (0));
+ EXPECT_EQ(607 , message.packed_fixed32 (0));
+ EXPECT_EQ(608 , message.packed_fixed64 (0));
+ EXPECT_EQ(609 , message.packed_sfixed32(0));
+ EXPECT_EQ(610 , message.packed_sfixed64(0));
+ EXPECT_EQ(611 , message.packed_float (0));
+ EXPECT_EQ(612 , message.packed_double (0));
+ EXPECT_EQ(true , message.packed_bool (0));
+ EXPECT_EQ(unittest::FOREIGN_BAR, message.packed_enum(0));
+
+ EXPECT_EQ(701 , message.packed_int32 (1));
+ EXPECT_EQ(702 , message.packed_int64 (1));
+ EXPECT_EQ(703 , message.packed_uint32 (1));
+ EXPECT_EQ(704 , message.packed_uint64 (1));
+ EXPECT_EQ(705 , message.packed_sint32 (1));
+ EXPECT_EQ(706 , message.packed_sint64 (1));
+ EXPECT_EQ(707 , message.packed_fixed32 (1));
+ EXPECT_EQ(708 , message.packed_fixed64 (1));
+ EXPECT_EQ(709 , message.packed_sfixed32(1));
+ EXPECT_EQ(710 , message.packed_sfixed64(1));
+ EXPECT_EQ(711 , message.packed_float (1));
+ EXPECT_EQ(712 , message.packed_double (1));
+ EXPECT_EQ(false, message.packed_bool (1));
+ EXPECT_EQ(unittest::FOREIGN_BAZ, message.packed_enum(1));
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ExpectPackedClear(
+ const unittest::TestPackedTypes& message) {
+ // Packed repeated fields are empty.
+ EXPECT_EQ(0, message.packed_int32_size ());
+ EXPECT_EQ(0, message.packed_int64_size ());
+ EXPECT_EQ(0, message.packed_uint32_size ());
+ EXPECT_EQ(0, message.packed_uint64_size ());
+ EXPECT_EQ(0, message.packed_sint32_size ());
+ EXPECT_EQ(0, message.packed_sint64_size ());
+ EXPECT_EQ(0, message.packed_fixed32_size ());
+ EXPECT_EQ(0, message.packed_fixed64_size ());
+ EXPECT_EQ(0, message.packed_sfixed32_size());
+ EXPECT_EQ(0, message.packed_sfixed64_size());
+ EXPECT_EQ(0, message.packed_float_size ());
+ EXPECT_EQ(0, message.packed_double_size ());
+ EXPECT_EQ(0, message.packed_bool_size ());
+ EXPECT_EQ(0, message.packed_enum_size ());
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ExpectPackedFieldsModified(
+ const unittest::TestPackedTypes& message) {
+ // Do the same for packed repeated fields.
+ ASSERT_EQ(2, message.packed_int32_size ());
+ ASSERT_EQ(2, message.packed_int64_size ());
+ ASSERT_EQ(2, message.packed_uint32_size ());
+ ASSERT_EQ(2, message.packed_uint64_size ());
+ ASSERT_EQ(2, message.packed_sint32_size ());
+ ASSERT_EQ(2, message.packed_sint64_size ());
+ ASSERT_EQ(2, message.packed_fixed32_size ());
+ ASSERT_EQ(2, message.packed_fixed64_size ());
+ ASSERT_EQ(2, message.packed_sfixed32_size());
+ ASSERT_EQ(2, message.packed_sfixed64_size());
+ ASSERT_EQ(2, message.packed_float_size ());
+ ASSERT_EQ(2, message.packed_double_size ());
+ ASSERT_EQ(2, message.packed_bool_size ());
+ ASSERT_EQ(2, message.packed_enum_size ());
+
+ EXPECT_EQ(601 , message.packed_int32 (0));
+ EXPECT_EQ(602 , message.packed_int64 (0));
+ EXPECT_EQ(603 , message.packed_uint32 (0));
+ EXPECT_EQ(604 , message.packed_uint64 (0));
+ EXPECT_EQ(605 , message.packed_sint32 (0));
+ EXPECT_EQ(606 , message.packed_sint64 (0));
+ EXPECT_EQ(607 , message.packed_fixed32 (0));
+ EXPECT_EQ(608 , message.packed_fixed64 (0));
+ EXPECT_EQ(609 , message.packed_sfixed32(0));
+ EXPECT_EQ(610 , message.packed_sfixed64(0));
+ EXPECT_EQ(611 , message.packed_float (0));
+ EXPECT_EQ(612 , message.packed_double (0));
+ EXPECT_EQ(true , message.packed_bool (0));
+ EXPECT_EQ(unittest::FOREIGN_BAR, message.packed_enum(0));
+ // Actually verify the second (modified) elements now.
+ EXPECT_EQ(801 , message.packed_int32 (1));
+ EXPECT_EQ(802 , message.packed_int64 (1));
+ EXPECT_EQ(803 , message.packed_uint32 (1));
+ EXPECT_EQ(804 , message.packed_uint64 (1));
+ EXPECT_EQ(805 , message.packed_sint32 (1));
+ EXPECT_EQ(806 , message.packed_sint64 (1));
+ EXPECT_EQ(807 , message.packed_fixed32 (1));
+ EXPECT_EQ(808 , message.packed_fixed64 (1));
+ EXPECT_EQ(809 , message.packed_sfixed32(1));
+ EXPECT_EQ(810 , message.packed_sfixed64(1));
+ EXPECT_EQ(811 , message.packed_float (1));
+ EXPECT_EQ(812 , message.packed_double (1));
+ EXPECT_EQ(true , message.packed_bool (1));
+ EXPECT_EQ(unittest::FOREIGN_FOO, message.packed_enum(1));
+}
+
// ===================================================================
// Extensions
//
@@ -1246,6 +1420,183 @@ void TestUtil::ExpectRepeatedExtensionsModified(
// -------------------------------------------------------------------
+void TestUtil::SetPackedExtensions(unittest::TestPackedExtensions* message) {
+ message->AddExtension(unittest::packed_int32_extension , 601);
+ message->AddExtension(unittest::packed_int64_extension , 602);
+ message->AddExtension(unittest::packed_uint32_extension , 603);
+ message->AddExtension(unittest::packed_uint64_extension , 604);
+ message->AddExtension(unittest::packed_sint32_extension , 605);
+ message->AddExtension(unittest::packed_sint64_extension , 606);
+ message->AddExtension(unittest::packed_fixed32_extension , 607);
+ message->AddExtension(unittest::packed_fixed64_extension , 608);
+ message->AddExtension(unittest::packed_sfixed32_extension, 609);
+ message->AddExtension(unittest::packed_sfixed64_extension, 610);
+ message->AddExtension(unittest::packed_float_extension , 611);
+ message->AddExtension(unittest::packed_double_extension , 612);
+ message->AddExtension(unittest::packed_bool_extension , true);
+ message->AddExtension(unittest::packed_enum_extension, unittest::FOREIGN_BAR);
+ // add a second one of each field
+ message->AddExtension(unittest::packed_int32_extension , 701);
+ message->AddExtension(unittest::packed_int64_extension , 702);
+ message->AddExtension(unittest::packed_uint32_extension , 703);
+ message->AddExtension(unittest::packed_uint64_extension , 704);
+ message->AddExtension(unittest::packed_sint32_extension , 705);
+ message->AddExtension(unittest::packed_sint64_extension , 706);
+ message->AddExtension(unittest::packed_fixed32_extension , 707);
+ message->AddExtension(unittest::packed_fixed64_extension , 708);
+ message->AddExtension(unittest::packed_sfixed32_extension, 709);
+ message->AddExtension(unittest::packed_sfixed64_extension, 710);
+ message->AddExtension(unittest::packed_float_extension , 711);
+ message->AddExtension(unittest::packed_double_extension , 712);
+ message->AddExtension(unittest::packed_bool_extension , false);
+ message->AddExtension(unittest::packed_enum_extension, unittest::FOREIGN_BAZ);
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ModifyPackedExtensions(unittest::TestPackedExtensions* message) {
+ message->SetExtension(unittest::packed_int32_extension , 1, 801);
+ message->SetExtension(unittest::packed_int64_extension , 1, 802);
+ message->SetExtension(unittest::packed_uint32_extension , 1, 803);
+ message->SetExtension(unittest::packed_uint64_extension , 1, 804);
+ message->SetExtension(unittest::packed_sint32_extension , 1, 805);
+ message->SetExtension(unittest::packed_sint64_extension , 1, 806);
+ message->SetExtension(unittest::packed_fixed32_extension , 1, 807);
+ message->SetExtension(unittest::packed_fixed64_extension , 1, 808);
+ message->SetExtension(unittest::packed_sfixed32_extension, 1, 809);
+ message->SetExtension(unittest::packed_sfixed64_extension, 1, 810);
+ message->SetExtension(unittest::packed_float_extension , 1, 811);
+ message->SetExtension(unittest::packed_double_extension , 1, 812);
+ message->SetExtension(unittest::packed_bool_extension , 1, true);
+ message->SetExtension(unittest::packed_enum_extension , 1,
+ unittest::FOREIGN_FOO);
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ExpectPackedExtensionsSet(
+ const unittest::TestPackedExtensions& message) {
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int32_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int64_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint32_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint64_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint32_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint64_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed32_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed64_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed32_extension));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed64_extension));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_float_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_double_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_bool_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_enum_extension ));
+
+ EXPECT_EQ(601 , message.GetExtension(unittest::packed_int32_extension , 0));
+ EXPECT_EQ(602 , message.GetExtension(unittest::packed_int64_extension , 0));
+ EXPECT_EQ(603 , message.GetExtension(unittest::packed_uint32_extension , 0));
+ EXPECT_EQ(604 , message.GetExtension(unittest::packed_uint64_extension , 0));
+ EXPECT_EQ(605 , message.GetExtension(unittest::packed_sint32_extension , 0));
+ EXPECT_EQ(606 , message.GetExtension(unittest::packed_sint64_extension , 0));
+ EXPECT_EQ(607 , message.GetExtension(unittest::packed_fixed32_extension , 0));
+ EXPECT_EQ(608 , message.GetExtension(unittest::packed_fixed64_extension , 0));
+ EXPECT_EQ(609 , message.GetExtension(unittest::packed_sfixed32_extension, 0));
+ EXPECT_EQ(610 , message.GetExtension(unittest::packed_sfixed64_extension, 0));
+ EXPECT_EQ(611 , message.GetExtension(unittest::packed_float_extension , 0));
+ EXPECT_EQ(612 , message.GetExtension(unittest::packed_double_extension , 0));
+ EXPECT_EQ(true , message.GetExtension(unittest::packed_bool_extension , 0));
+ EXPECT_EQ(unittest::FOREIGN_BAR,
+ message.GetExtension(unittest::packed_enum_extension, 0));
+ EXPECT_EQ(701 , message.GetExtension(unittest::packed_int32_extension , 1));
+ EXPECT_EQ(702 , message.GetExtension(unittest::packed_int64_extension , 1));
+ EXPECT_EQ(703 , message.GetExtension(unittest::packed_uint32_extension , 1));
+ EXPECT_EQ(704 , message.GetExtension(unittest::packed_uint64_extension , 1));
+ EXPECT_EQ(705 , message.GetExtension(unittest::packed_sint32_extension , 1));
+ EXPECT_EQ(706 , message.GetExtension(unittest::packed_sint64_extension , 1));
+ EXPECT_EQ(707 , message.GetExtension(unittest::packed_fixed32_extension , 1));
+ EXPECT_EQ(708 , message.GetExtension(unittest::packed_fixed64_extension , 1));
+ EXPECT_EQ(709 , message.GetExtension(unittest::packed_sfixed32_extension, 1));
+ EXPECT_EQ(710 , message.GetExtension(unittest::packed_sfixed64_extension, 1));
+ EXPECT_EQ(711 , message.GetExtension(unittest::packed_float_extension , 1));
+ EXPECT_EQ(712 , message.GetExtension(unittest::packed_double_extension , 1));
+ EXPECT_EQ(false, message.GetExtension(unittest::packed_bool_extension , 1));
+ EXPECT_EQ(unittest::FOREIGN_BAZ,
+ message.GetExtension(unittest::packed_enum_extension, 1));
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ExpectPackedExtensionsClear(
+ const unittest::TestPackedExtensions& message) {
+ EXPECT_EQ(0, message.ExtensionSize(unittest::packed_int32_extension ));
+ EXPECT_EQ(0, message.ExtensionSize(unittest::packed_int64_extension ));
+ EXPECT_EQ(0, message.ExtensionSize(unittest::packed_uint32_extension ));
+ EXPECT_EQ(0, message.ExtensionSize(unittest::packed_uint64_extension ));
+ EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sint32_extension ));
+ EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sint64_extension ));
+ EXPECT_EQ(0, message.ExtensionSize(unittest::packed_fixed32_extension ));
+ EXPECT_EQ(0, message.ExtensionSize(unittest::packed_fixed64_extension ));
+ EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sfixed32_extension));
+ EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sfixed64_extension));
+ EXPECT_EQ(0, message.ExtensionSize(unittest::packed_float_extension ));
+ EXPECT_EQ(0, message.ExtensionSize(unittest::packed_double_extension ));
+ EXPECT_EQ(0, message.ExtensionSize(unittest::packed_bool_extension ));
+ EXPECT_EQ(0, message.ExtensionSize(unittest::packed_enum_extension ));
+}
+
+// -------------------------------------------------------------------
+
+void TestUtil::ExpectPackedExtensionsModified(
+ const unittest::TestPackedExtensions& message) {
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int32_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int64_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint32_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint64_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint32_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint64_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed32_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed64_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed32_extension));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed64_extension));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_float_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_double_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_bool_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::packed_enum_extension ));
+ EXPECT_EQ(601 , message.GetExtension(unittest::packed_int32_extension , 0));
+ EXPECT_EQ(602 , message.GetExtension(unittest::packed_int64_extension , 0));
+ EXPECT_EQ(603 , message.GetExtension(unittest::packed_uint32_extension , 0));
+ EXPECT_EQ(604 , message.GetExtension(unittest::packed_uint64_extension , 0));
+ EXPECT_EQ(605 , message.GetExtension(unittest::packed_sint32_extension , 0));
+ EXPECT_EQ(606 , message.GetExtension(unittest::packed_sint64_extension , 0));
+ EXPECT_EQ(607 , message.GetExtension(unittest::packed_fixed32_extension , 0));
+ EXPECT_EQ(608 , message.GetExtension(unittest::packed_fixed64_extension , 0));
+ EXPECT_EQ(609 , message.GetExtension(unittest::packed_sfixed32_extension, 0));
+ EXPECT_EQ(610 , message.GetExtension(unittest::packed_sfixed64_extension, 0));
+ EXPECT_EQ(611 , message.GetExtension(unittest::packed_float_extension , 0));
+ EXPECT_EQ(612 , message.GetExtension(unittest::packed_double_extension , 0));
+ EXPECT_EQ(true , message.GetExtension(unittest::packed_bool_extension , 0));
+ EXPECT_EQ(unittest::FOREIGN_BAR,
+ message.GetExtension(unittest::packed_enum_extension, 0));
+
+ // Actually verify the second (modified) elements now.
+ EXPECT_EQ(801 , message.GetExtension(unittest::packed_int32_extension , 1));
+ EXPECT_EQ(802 , message.GetExtension(unittest::packed_int64_extension , 1));
+ EXPECT_EQ(803 , message.GetExtension(unittest::packed_uint32_extension , 1));
+ EXPECT_EQ(804 , message.GetExtension(unittest::packed_uint64_extension , 1));
+ EXPECT_EQ(805 , message.GetExtension(unittest::packed_sint32_extension , 1));
+ EXPECT_EQ(806 , message.GetExtension(unittest::packed_sint64_extension , 1));
+ EXPECT_EQ(807 , message.GetExtension(unittest::packed_fixed32_extension , 1));
+ EXPECT_EQ(808 , message.GetExtension(unittest::packed_fixed64_extension , 1));
+ EXPECT_EQ(809 , message.GetExtension(unittest::packed_sfixed32_extension, 1));
+ EXPECT_EQ(810 , message.GetExtension(unittest::packed_sfixed64_extension, 1));
+ EXPECT_EQ(811 , message.GetExtension(unittest::packed_float_extension , 1));
+ EXPECT_EQ(812 , message.GetExtension(unittest::packed_double_extension , 1));
+ EXPECT_EQ(true , message.GetExtension(unittest::packed_bool_extension , 1));
+ EXPECT_EQ(unittest::FOREIGN_FOO,
+ message.GetExtension(unittest::packed_enum_extension, 1));
+}
+
+// -------------------------------------------------------------------
+
void TestUtil::ExpectAllFieldsAndExtensionsInOrder(const string& serialized) {
// We set each field individually, serialize separately, and concatenate all
// the strings in canonical order to determine the expected serialization.
@@ -1335,7 +1686,8 @@ TestUtil::ReflectionTester::ReflectionTester(
// Shorthand to get a FieldDescriptor for a field of unittest::TestAllTypes.
const FieldDescriptor* TestUtil::ReflectionTester::F(const string& name) {
const FieldDescriptor* result = NULL;
- if (base_descriptor_->name() == "TestAllExtensions") {
+ if (base_descriptor_->name() == "TestAllExtensions" ||
+ base_descriptor_->name() == "TestPackedExtensions") {
result = base_descriptor_->file()->FindExtensionByName(name + "_extension");
} else {
result = base_descriptor_->FindFieldByName(name);
@@ -1475,6 +1827,40 @@ void TestUtil::ReflectionTester::SetAllFieldsViaReflection(Message* message) {
reflection->SetString(message, F("default_cord"), "425");
}
+void TestUtil::ReflectionTester::SetPackedFieldsViaReflection(
+ Message* message) {
+ const Reflection* reflection = message->GetReflection();
+ reflection->AddInt32 (message, F("packed_int32" ), 601);
+ reflection->AddInt64 (message, F("packed_int64" ), 602);
+ reflection->AddUInt32(message, F("packed_uint32" ), 603);
+ reflection->AddUInt64(message, F("packed_uint64" ), 604);
+ reflection->AddInt32 (message, F("packed_sint32" ), 605);
+ reflection->AddInt64 (message, F("packed_sint64" ), 606);
+ reflection->AddUInt32(message, F("packed_fixed32" ), 607);
+ reflection->AddUInt64(message, F("packed_fixed64" ), 608);
+ reflection->AddInt32 (message, F("packed_sfixed32"), 609);
+ reflection->AddInt64 (message, F("packed_sfixed64"), 610);
+ reflection->AddFloat (message, F("packed_float" ), 611);
+ reflection->AddDouble(message, F("packed_double" ), 612);
+ reflection->AddBool (message, F("packed_bool" ), true);
+ reflection->AddEnum (message, F("packed_enum" ), foreign_bar_);
+
+ reflection->AddInt32 (message, F("packed_int32" ), 701);
+ reflection->AddInt64 (message, F("packed_int64" ), 702);
+ reflection->AddUInt32(message, F("packed_uint32" ), 703);
+ reflection->AddUInt64(message, F("packed_uint64" ), 704);
+ reflection->AddInt32 (message, F("packed_sint32" ), 705);
+ reflection->AddInt64 (message, F("packed_sint64" ), 706);
+ reflection->AddUInt32(message, F("packed_fixed32" ), 707);
+ reflection->AddUInt64(message, F("packed_fixed64" ), 708);
+ reflection->AddInt32 (message, F("packed_sfixed32"), 709);
+ reflection->AddInt64 (message, F("packed_sfixed64"), 710);
+ reflection->AddFloat (message, F("packed_float" ), 711);
+ reflection->AddDouble(message, F("packed_double" ), 712);
+ reflection->AddBool (message, F("packed_bool" ), false);
+ reflection->AddEnum (message, F("packed_enum" ), foreign_baz_);
+}
+
// -------------------------------------------------------------------
void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection(
@@ -1725,6 +2111,58 @@ void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection(
EXPECT_EQ("425", reflection->GetStringReference(message, F("default_cord"), &scratch));
}
+void TestUtil::ReflectionTester::ExpectPackedFieldsSetViaReflection(
+ const Message& message) {
+ const Reflection* reflection = message.GetReflection();
+
+ ASSERT_EQ(2, reflection->FieldSize(message, F("packed_int32" )));
+ ASSERT_EQ(2, reflection->FieldSize(message, F("packed_int64" )));
+ ASSERT_EQ(2, reflection->FieldSize(message, F("packed_uint32" )));
+ ASSERT_EQ(2, reflection->FieldSize(message, F("packed_uint64" )));
+ ASSERT_EQ(2, reflection->FieldSize(message, F("packed_sint32" )));
+ ASSERT_EQ(2, reflection->FieldSize(message, F("packed_sint64" )));
+ ASSERT_EQ(2, reflection->FieldSize(message, F("packed_fixed32" )));
+ ASSERT_EQ(2, reflection->FieldSize(message, F("packed_fixed64" )));
+ ASSERT_EQ(2, reflection->FieldSize(message, F("packed_sfixed32")));
+ ASSERT_EQ(2, reflection->FieldSize(message, F("packed_sfixed64")));
+ ASSERT_EQ(2, reflection->FieldSize(message, F("packed_float" )));
+ ASSERT_EQ(2, reflection->FieldSize(message, F("packed_double" )));
+ ASSERT_EQ(2, reflection->FieldSize(message, F("packed_bool" )));
+ ASSERT_EQ(2, reflection->FieldSize(message, F("packed_enum" )));
+
+ EXPECT_EQ(601 , reflection->GetRepeatedInt32 (message, F("packed_int32" ), 0));
+ EXPECT_EQ(602 , reflection->GetRepeatedInt64 (message, F("packed_int64" ), 0));
+ EXPECT_EQ(603 , reflection->GetRepeatedUInt32(message, F("packed_uint32" ), 0));
+ EXPECT_EQ(604 , reflection->GetRepeatedUInt64(message, F("packed_uint64" ), 0));
+ EXPECT_EQ(605 , reflection->GetRepeatedInt32 (message, F("packed_sint32" ), 0));
+ EXPECT_EQ(606 , reflection->GetRepeatedInt64 (message, F("packed_sint64" ), 0));
+ EXPECT_EQ(607 , reflection->GetRepeatedUInt32(message, F("packed_fixed32" ), 0));
+ EXPECT_EQ(608 , reflection->GetRepeatedUInt64(message, F("packed_fixed64" ), 0));
+ EXPECT_EQ(609 , reflection->GetRepeatedInt32 (message, F("packed_sfixed32"), 0));
+ EXPECT_EQ(610 , reflection->GetRepeatedInt64 (message, F("packed_sfixed64"), 0));
+ EXPECT_EQ(611 , reflection->GetRepeatedFloat (message, F("packed_float" ), 0));
+ EXPECT_EQ(612 , reflection->GetRepeatedDouble(message, F("packed_double" ), 0));
+ EXPECT_EQ(true , reflection->GetRepeatedBool (message, F("packed_bool" ), 0));
+ EXPECT_EQ(foreign_bar_,
+ reflection->GetRepeatedEnum(message, F("packed_enum"), 0));
+
+ EXPECT_EQ(701 , reflection->GetRepeatedInt32 (message, F("packed_int32" ), 1));
+ EXPECT_EQ(702 , reflection->GetRepeatedInt64 (message, F("packed_int64" ), 1));
+ EXPECT_EQ(703 , reflection->GetRepeatedUInt32(message, F("packed_uint32" ), 1));
+ EXPECT_EQ(704 , reflection->GetRepeatedUInt64(message, F("packed_uint64" ), 1));
+ EXPECT_EQ(705 , reflection->GetRepeatedInt32 (message, F("packed_sint32" ), 1));
+ EXPECT_EQ(706 , reflection->GetRepeatedInt64 (message, F("packed_sint64" ), 1));
+ EXPECT_EQ(707 , reflection->GetRepeatedUInt32(message, F("packed_fixed32" ), 1));
+ EXPECT_EQ(708 , reflection->GetRepeatedUInt64(message, F("packed_fixed64" ), 1));
+ EXPECT_EQ(709 , reflection->GetRepeatedInt32 (message, F("packed_sfixed32"), 1));
+ EXPECT_EQ(710 , reflection->GetRepeatedInt64 (message, F("packed_sfixed64"), 1));
+ EXPECT_EQ(711 , reflection->GetRepeatedFloat (message, F("packed_float" ), 1));
+ EXPECT_EQ(712 , reflection->GetRepeatedDouble(message, F("packed_double" ), 1));
+ EXPECT_EQ(false, reflection->GetRepeatedBool (message, F("packed_bool" ), 1));
+ EXPECT_EQ(foreign_baz_,
+ reflection->GetRepeatedEnum(message, F("packed_enum"), 1));
+}
+
// -------------------------------------------------------------------
void TestUtil::ReflectionTester::ExpectClearViaReflection(
@@ -1890,6 +2328,26 @@ void TestUtil::ReflectionTester::ExpectClearViaReflection(
EXPECT_EQ("123", reflection->GetStringReference(message, F("default_cord"), &scratch));
}
+void TestUtil::ReflectionTester::ExpectPackedClearViaReflection(
+ const Message& message) {
+ const Reflection* reflection = message.GetReflection();
+
+ EXPECT_EQ(0, reflection->FieldSize(message, F("packed_int32" )));
+ EXPECT_EQ(0, reflection->FieldSize(message, F("packed_int64" )));
+ EXPECT_EQ(0, reflection->FieldSize(message, F("packed_uint32" )));
+ EXPECT_EQ(0, reflection->FieldSize(message, F("packed_uint64" )));
+ EXPECT_EQ(0, reflection->FieldSize(message, F("packed_sint32" )));
+ EXPECT_EQ(0, reflection->FieldSize(message, F("packed_sint64" )));
+ EXPECT_EQ(0, reflection->FieldSize(message, F("packed_fixed32" )));
+ EXPECT_EQ(0, reflection->FieldSize(message, F("packed_fixed64" )));
+ EXPECT_EQ(0, reflection->FieldSize(message, F("packed_sfixed32")));
+ EXPECT_EQ(0, reflection->FieldSize(message, F("packed_sfixed64")));
+ EXPECT_EQ(0, reflection->FieldSize(message, F("packed_float" )));
+ EXPECT_EQ(0, reflection->FieldSize(message, F("packed_double" )));
+ EXPECT_EQ(0, reflection->FieldSize(message, F("packed_bool" )));
+ EXPECT_EQ(0, reflection->FieldSize(message, F("packed_enum" )));
+}
+
// -------------------------------------------------------------------
void TestUtil::ReflectionTester::ModifyRepeatedFieldsViaReflection(
@@ -1930,5 +2388,24 @@ void TestUtil::ReflectionTester::ModifyRepeatedFieldsViaReflection(
reflection->SetRepeatedString(message, F("repeated_cord"), 1, "525");
}
+void TestUtil::ReflectionTester::ModifyPackedFieldsViaReflection(
+ Message* message) {
+ const Reflection* reflection = message->GetReflection();
+ reflection->SetRepeatedInt32 (message, F("packed_int32" ), 1, 801);
+ reflection->SetRepeatedInt64 (message, F("packed_int64" ), 1, 802);
+ reflection->SetRepeatedUInt32(message, F("packed_uint32" ), 1, 803);
+ reflection->SetRepeatedUInt64(message, F("packed_uint64" ), 1, 804);
+ reflection->SetRepeatedInt32 (message, F("packed_sint32" ), 1, 805);
+ reflection->SetRepeatedInt64 (message, F("packed_sint64" ), 1, 806);
+ reflection->SetRepeatedUInt32(message, F("packed_fixed32" ), 1, 807);
+ reflection->SetRepeatedUInt64(message, F("packed_fixed64" ), 1, 808);
+ reflection->SetRepeatedInt32 (message, F("packed_sfixed32"), 1, 809);
+ reflection->SetRepeatedInt64 (message, F("packed_sfixed64"), 1, 810);
+ reflection->SetRepeatedFloat (message, F("packed_float" ), 1, 811);
+ reflection->SetRepeatedDouble(message, F("packed_double" ), 1, 812);
+ reflection->SetRepeatedBool (message, F("packed_bool" ), 1, true);
+ reflection->SetRepeatedEnum (message, F("packed_enum" ), 1, foreign_foo_);
+}
+
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/test_util.h b/src/google/protobuf/test_util.h
index af03afc3..ca840c71 100644
--- a/src/google/protobuf/test_util.h
+++ b/src/google/protobuf/test_util.h
@@ -52,30 +52,44 @@ class TestUtil {
static void SetAllFields(unittest::TestAllTypes* message);
static void SetAllExtensions(unittest::TestAllExtensions* message);
static void SetAllFieldsAndExtensions(unittest::TestFieldOrderings* message);
+ static void SetPackedFields(unittest::TestPackedTypes* message);
+ static void SetPackedExtensions(unittest::TestPackedExtensions* message);
// Use the repeated versions of the set_*() accessors to modify all the
// repeated fields of the messsage (which should already have been
- // initialized with SetAllFields()). SetAllFields() itself only tests
+ // initialized with Set*Fields()). Set*Fields() itself only tests
// the add_*() accessors.
static void ModifyRepeatedFields(unittest::TestAllTypes* message);
static void ModifyRepeatedExtensions(unittest::TestAllExtensions* message);
+ static void ModifyPackedFields(unittest::TestPackedTypes* message);
+ static void ModifyPackedExtensions(unittest::TestPackedExtensions* message);
// Check that all fields have the values that they should have after
- // SetAllFields() is called.
+ // Set*Fields() is called.
static void ExpectAllFieldsSet(const unittest::TestAllTypes& message);
static void ExpectAllExtensionsSet(
const unittest::TestAllExtensions& message);
+ static void ExpectPackedFieldsSet(const unittest::TestPackedTypes& message);
+ static void ExpectPackedExtensionsSet(
+ const unittest::TestPackedExtensions& message);
// Expect that the message is modified as would be expected from
- // ModifyRepeatedFields().
+ // Modify*Fields().
static void ExpectRepeatedFieldsModified(
const unittest::TestAllTypes& message);
static void ExpectRepeatedExtensionsModified(
const unittest::TestAllExtensions& message);
+ static void ExpectPackedFieldsModified(
+ const unittest::TestPackedTypes& message);
+ static void ExpectPackedExtensionsModified(
+ const unittest::TestPackedExtensions& message);
// Check that all fields have their default values.
static void ExpectClear(const unittest::TestAllTypes& message);
static void ExpectExtensionsClear(const unittest::TestAllExtensions& message);
+ static void ExpectPackedClear(const unittest::TestPackedTypes& message);
+ static void ExpectPackedExtensionsClear(
+ const unittest::TestPackedExtensions& message);
// Check that the passed-in serialization is the canonical serialization we
// expect for a TestFieldOrderings message filled in by
@@ -97,6 +111,11 @@ class TestUtil {
void ExpectAllFieldsSetViaReflection(const Message& message);
void ExpectClearViaReflection(const Message& message);
+ void SetPackedFieldsViaReflection(Message* message);
+ void ModifyPackedFieldsViaReflection(Message* message);
+ void ExpectPackedFieldsSetViaReflection(const Message& message);
+ void ExpectPackedClearViaReflection(const Message& message);
+
private:
const FieldDescriptor* F(const string& name);
diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto
index 0aa66b9f..46ce77c3 100644
--- a/src/google/protobuf/unittest.proto
+++ b/src/google/protobuf/unittest.proto
@@ -461,6 +461,46 @@ message OneBytes {
optional bytes data = 1;
}
+// Test messages for packed fields
+
+message TestPackedTypes {
+ repeated int32 packed_int32 = 90 [packed = true];
+ repeated int64 packed_int64 = 91 [packed = true];
+ repeated uint32 packed_uint32 = 92 [packed = true];
+ repeated uint64 packed_uint64 = 93 [packed = true];
+ repeated sint32 packed_sint32 = 94 [packed = true];
+ repeated sint64 packed_sint64 = 95 [packed = true];
+ repeated fixed32 packed_fixed32 = 96 [packed = true];
+ repeated fixed64 packed_fixed64 = 97 [packed = true];
+ repeated sfixed32 packed_sfixed32 = 98 [packed = true];
+ repeated sfixed64 packed_sfixed64 = 99 [packed = true];
+ repeated float packed_float = 100 [packed = true];
+ repeated double packed_double = 101 [packed = true];
+ repeated bool packed_bool = 102 [packed = true];
+ repeated ForeignEnum packed_enum = 103 [packed = true];
+}
+
+message TestPackedExtensions {
+ extensions 1 to max;
+}
+
+extend TestPackedExtensions {
+ repeated int32 packed_int32_extension = 90 [packed = true];
+ repeated int64 packed_int64_extension = 91 [packed = true];
+ repeated uint32 packed_uint32_extension = 92 [packed = true];
+ repeated uint64 packed_uint64_extension = 93 [packed = true];
+ repeated sint32 packed_sint32_extension = 94 [packed = true];
+ repeated sint64 packed_sint64_extension = 95 [packed = true];
+ repeated fixed32 packed_fixed32_extension = 96 [packed = true];
+ repeated fixed64 packed_fixed64_extension = 97 [packed = true];
+ repeated sfixed32 packed_sfixed32_extension = 98 [packed = true];
+ repeated sfixed64 packed_sfixed64_extension = 99 [packed = true];
+ repeated float packed_float_extension = 100 [packed = true];
+ repeated double packed_double_extension = 101 [packed = true];
+ repeated bool packed_bool_extension = 102 [packed = true];
+ repeated ForeignEnum packed_enum_extension = 103 [packed = true];
+}
+
// Test that RPC services work.
message FooRequest {}
message FooResponse {}
diff --git a/src/google/protobuf/unknown_field_set.cc b/src/google/protobuf/unknown_field_set.cc
index 6a9be5a4..f42f9a59 100644
--- a/src/google/protobuf/unknown_field_set.cc
+++ b/src/google/protobuf/unknown_field_set.cc
@@ -154,6 +154,46 @@ int UnknownFieldSet::SpaceUsed() const {
return sizeof(*this) + SpaceUsedExcludingSelf();
}
+UnknownFieldSet::Internal::FieldMap UnknownFieldSet::kEmptyMap;
+const UnknownFieldSet::iterator UnknownFieldSet::kEmptyIterator(
+ kEmptyMap.end(), &kEmptyMap);
+const UnknownFieldSet::const_iterator UnknownFieldSet::kEmptyConstIterator(
+ kEmptyMap.end(), &kEmptyMap);
+
+void UnknownFieldSet::iterator::AdvanceToNonEmpty() {
+ while (inner_iterator_ != inner_map_->end() &&
+ (inner_iterator_->second->index() == -1 ||
+ inner_iterator_->second->empty())) {
+ ++inner_iterator_;
+ }
+}
+
+void UnknownFieldSet::const_iterator::AdvanceToNonEmpty() {
+ while (inner_iterator_ != inner_map_->end() &&
+ (inner_iterator_->second->index() == -1 ||
+ inner_iterator_->second->empty())) {
+ ++inner_iterator_;
+ }
+}
+
+UnknownFieldSet::iterator UnknownFieldSet::begin() {
+ if (internal_ == NULL) return kEmptyIterator;
+
+ UnknownFieldSet::iterator result(internal_->fields_.begin(),
+ &internal_->fields_);
+ result.AdvanceToNonEmpty();
+ return result;
+}
+
+UnknownFieldSet::const_iterator UnknownFieldSet::begin() const {
+ if (internal_ == NULL) return kEmptyIterator;
+
+ UnknownFieldSet::const_iterator result(internal_->fields_.begin(),
+ &internal_->fields_);
+ result.AdvanceToNonEmpty();
+ return result;
+}
+
UnknownField::UnknownField(int number)
: number_(number),
index_(-1) {
diff --git a/src/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h
index 55eec6e2..f17012df 100644
--- a/src/google/protobuf/unknown_field_set.h
+++ b/src/google/protobuf/unknown_field_set.h
@@ -70,6 +70,13 @@ class LIBPROTOBUF_EXPORT UnknownFieldSet {
void Clear();
// Is this set empty?
+ //
+ // Note that this is equivalent to field_count() == 0 but is NOT necessarily
+ // equivalent to begin() == end(). The iterator class skips fields which are
+ // themselves empty, so if field_count() is non-zero but field(i)->empty() is
+ // true for all i, then begin() will be equal to end() but empty() will return
+ // false. This inconsistency almost never occurs in practice because typical
+ // code does not add empty fields to an UnknownFieldSet.
inline bool empty() const;
// Merge the contents of some other UnknownFieldSet with this one.
@@ -78,6 +85,117 @@ class LIBPROTOBUF_EXPORT UnknownFieldSet {
// Swaps the contents of some other UnknownFieldSet with this one.
inline void Swap(UnknownFieldSet* x);
+ // Find a field by field number. Returns NULL if not found.
+ const UnknownField* FindFieldByNumber(int number) const;
+
+ // Add a field by field number. If the field number already exists, returns
+ // the existing UnknownField.
+ UnknownField* AddField(int number);
+
+ // Computes (an estimate of) the total number of bytes currently used for
+ // storing the unknown fields in memory. Does NOT include
+ // sizeof(*this) in the calculation.
+ int SpaceUsedExcludingSelf() const;
+
+ // Version of SpaceUsed() including sizeof(*this).
+ int SpaceUsed() const;
+
+ // STL-style iteration ---------------------------------------------
+ // These iterate over the non-empty UnknownFields in order by field
+ // number. All iterators are invalidated whenever the UnknownFieldSet
+ // is modified.
+
+ class const_iterator;
+
+ class LIBPROTOBUF_EXPORT iterator {
+ public:
+ iterator() {}
+
+ bool operator==(const iterator& other) {
+ return inner_iterator_ == other.inner_iterator_;
+ }
+ bool operator!=(const iterator& other) {
+ return inner_iterator_ != other.inner_iterator_;
+ }
+
+ UnknownField& operator*() { return *inner_iterator_->second; }
+ UnknownField* operator->() { return inner_iterator_->second; }
+ iterator& operator++() {
+ ++inner_iterator_;
+ AdvanceToNonEmpty();
+ return *this;
+ }
+ iterator operator++(int) {
+ iterator copy(*this);
+ ++*this;
+ return copy;
+ }
+
+ private:
+ friend class UnknownFieldSet;
+ friend class LIBPROTOBUF_EXPORT UnknownFieldSet::const_iterator;
+ iterator(map<int, UnknownField*>::iterator inner_iterator,
+ map<int, UnknownField*>* inner_map)
+ : inner_iterator_(inner_iterator), inner_map_(inner_map) {}
+
+ void AdvanceToNonEmpty();
+
+ map<int, UnknownField*>::iterator inner_iterator_;
+ map<int, UnknownField*>* inner_map_;
+ };
+
+ class LIBPROTOBUF_EXPORT const_iterator {
+ public:
+ const_iterator() {}
+ const_iterator(const iterator& other)
+ : inner_iterator_(other.inner_iterator_), inner_map_(other.inner_map_) {}
+
+ bool operator==(const const_iterator& other) {
+ return inner_iterator_ == other.inner_iterator_;
+ }
+ bool operator!=(const const_iterator& other) {
+ return inner_iterator_ != other.inner_iterator_;
+ }
+
+ UnknownField& operator*() { return *inner_iterator_->second; }
+ UnknownField* operator->() { return inner_iterator_->second; }
+ const_iterator& operator++() {
+ ++inner_iterator_;
+ AdvanceToNonEmpty();
+ return *this;
+ }
+ const_iterator operator++(int) {
+ const_iterator copy(*this);
+ ++*this;
+ return copy;
+ }
+
+ private:
+ friend class UnknownFieldSet;
+ const_iterator(map<int, UnknownField*>::const_iterator inner_iterator,
+ const map<int, UnknownField*>* inner_map)
+ : inner_iterator_(inner_iterator), inner_map_(inner_map) {}
+
+ void AdvanceToNonEmpty();
+
+ map<int, UnknownField*>::const_iterator inner_iterator_;
+ const map<int, UnknownField*>* inner_map_;
+ };
+
+ iterator begin();
+ iterator end() {
+ return internal_ == NULL ? kEmptyIterator :
+ iterator(internal_->fields_.end(), &internal_->fields_);
+ }
+ const_iterator begin() const;
+ const_iterator end() const {
+ return internal_ == NULL ? kEmptyConstIterator :
+ const_iterator(internal_->fields_.end(), &internal_->fields_);
+ }
+
+ // Old-style iteration ---------------------------------------------
+ // New code should use begin() and end() rather than these methods.
+
// Returns the number of fields present in the UnknownFieldSet.
inline int field_count() const;
// Get a field in the set, where 0 <= index < field_count(). The fields
@@ -87,13 +205,6 @@ class LIBPROTOBUF_EXPORT UnknownFieldSet {
// 0 <= index < field_count(). The fields appear in arbitrary order.
inline UnknownField* mutable_field(int index);
- // Find a field by field number. Returns NULL if not found.
- const UnknownField* FindFieldByNumber(int number) const;
-
- // Add a field by field number. If the field number already exists, returns
- // the existing UnknownField.
- UnknownField* AddField(int number);
-
// Parsing helpers -------------------------------------------------
// These work exactly like the similarly-named methods of Message.
@@ -105,13 +216,6 @@ class LIBPROTOBUF_EXPORT UnknownFieldSet {
return ParseFromArray(data.data(), data.size());
}
- // Computes (an estimate of) the total number of bytes currently used for
- // storing the unknown fields in memory. Does NOT include
- // sizeof(*this) in the calculation.
- int SpaceUsedExcludingSelf() const;
- // Version of SpaceUsed() including sizeof(*this).
- int SpaceUsed() const;
-
private:
// "Active" fields are ones which have been added since the last time Clear()
// was called. Inactive fields are objects we are keeping around incase
@@ -139,6 +243,11 @@ class LIBPROTOBUF_EXPORT UnknownFieldSet {
// Don't keep more inactive fields than this.
static const int kMaxInactiveFields = 100;
+ // Used by begin() and end() when internal_ is NULL.
+ static Internal::FieldMap kEmptyMap;
+ static const iterator kEmptyIterator;
+ static const const_iterator kEmptyConstIterator;
+
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UnknownFieldSet);
};
@@ -160,6 +269,9 @@ class LIBPROTOBUF_EXPORT UnknownField {
// Clears all fields.
void Clear();
+ // Is this field empty? (I.e. all of the *_size() methods return zero.)
+ inline bool empty() const;
+
// Merge the contents of some other UnknownField with this one. For each
// wire type, the values are simply concatenated.
void MergeFrom(const UnknownField& other);
@@ -256,6 +368,14 @@ inline UnknownField* UnknownFieldSet::mutable_field(int index) {
return internal_->active_fields_[index];
}
+inline bool UnknownField::empty() const {
+ return varint_.size() == 0 &&
+ fixed32_.size() == 0 &&
+ fixed64_.size() == 0 &&
+ length_delimited_.size() == 0 &&
+ group_.size() == 0;
+}
+
inline int UnknownField::number() const { return number_; }
inline int UnknownField::index () const { return index_; }
@@ -322,8 +442,8 @@ inline UnknownFieldSet* UnknownField::add_group() {
}
inline void UnknownField::clear_varint () { varint_.Clear(); }
-inline void UnknownField::clear_fixed32() { varint_.Clear(); }
-inline void UnknownField::clear_fixed64() { varint_.Clear(); }
+inline void UnknownField::clear_fixed32() { fixed32_.Clear(); }
+inline void UnknownField::clear_fixed64() { fixed64_.Clear(); }
inline void UnknownField::clear_length_delimited() {
length_delimited_.Clear();
}
diff --git a/src/google/protobuf/unknown_field_set_unittest.cc b/src/google/protobuf/unknown_field_set_unittest.cc
index c7e78b23..0a75af9f 100644
--- a/src/google/protobuf/unknown_field_set_unittest.cc
+++ b/src/google/protobuf/unknown_field_set_unittest.cc
@@ -516,6 +516,92 @@ TEST_F(UnknownFieldSetTest, SpaceUsed) {
EXPECT_EQ(expected_size, unknown_fields.SpaceUsed());
}
+TEST_F(UnknownFieldSetTest, Empty) {
+ UnknownFieldSet unknown_fields;
+ EXPECT_TRUE(unknown_fields.empty());
+ unknown_fields.AddField(6)->add_varint(123);
+ EXPECT_FALSE(unknown_fields.empty());
+ unknown_fields.Clear();
+ EXPECT_TRUE(unknown_fields.empty());
+}
+
+TEST_F(UnknownFieldSetTest, FieldEmpty) {
+ UnknownFieldSet unknown_fields;
+ UnknownField* field = unknown_fields.AddField(1);
+
+ EXPECT_TRUE(field->empty());
+
+ field->add_varint(1);
+ EXPECT_FALSE(field->empty());
+ field->Clear();
+ EXPECT_TRUE(field->empty());
+
+ field->add_fixed32(1);
+ EXPECT_FALSE(field->empty());
+ field->Clear();
+ EXPECT_TRUE(field->empty());
+
+ field->add_fixed64(1);
+ EXPECT_FALSE(field->empty());
+ field->Clear();
+ EXPECT_TRUE(field->empty());
+
+ field->add_length_delimited("foo");
+ EXPECT_FALSE(field->empty());
+ field->Clear();
+ EXPECT_TRUE(field->empty());
+
+ field->add_group();
+ EXPECT_FALSE(field->empty());
+ field->Clear();
+ EXPECT_TRUE(field->empty());
+}
+
+TEST_F(UnknownFieldSetTest, Iterator) {
+ UnknownFieldSet unknown_fields;
+ EXPECT_TRUE(unknown_fields.begin() == unknown_fields.end());
+
+ // Populate the UnknownFieldSet with some inactive fields by adding some
+ // fields and then clearing.
+ unknown_fields.AddField(6);
+ unknown_fields.AddField(4);
+ unknown_fields.Clear();
+
+ // Add a bunch of "active" fields.
+ UnknownField* a = unknown_fields.AddField(5);
+ unknown_fields.AddField(3);
+ unknown_fields.AddField(9);
+ unknown_fields.AddField(1);
+ UnknownField* b = unknown_fields.AddField(2);
+
+ // Only make some of them non-empty.
+ a->add_varint(1);
+ b->add_length_delimited("foo");
+
+ // Iterate!
+ {
+ UnknownFieldSet::iterator iter = unknown_fields.begin();
+ ASSERT_TRUE(iter != unknown_fields.end());
+ EXPECT_EQ(b, &*iter);
+ ++iter;
+ ASSERT_TRUE(iter != unknown_fields.end());
+ EXPECT_EQ(a, &*iter);
+ ++iter;
+ EXPECT_TRUE(iter == unknown_fields.end());
+ }
+
+ {
+ UnknownFieldSet::const_iterator iter = unknown_fields.begin();
+ ASSERT_TRUE(iter != unknown_fields.end());
+ EXPECT_EQ(b, &*iter);
+ ++iter;
+ ASSERT_TRUE(iter != unknown_fields.end());
+ EXPECT_EQ(a, &*iter);
+ ++iter;
+ EXPECT_TRUE(iter == unknown_fields.end());
+ }
+}
+
} // namespace
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc
index 99ea619b..aeea3ccb 100644
--- a/src/google/protobuf/wire_format.cc
+++ b/src/google/protobuf/wire_format.cc
@@ -369,93 +369,155 @@ bool WireFormat::ParseAndMergeField(
const Reflection* message_reflection = message->GetReflection();
if (field == NULL ||
- GetTagWireType(tag) != WireTypeForFieldType(field->type())) {
+ GetTagWireType(tag) != WireTypeForField(field)) {
// We don't recognize this field. Either the field number is unknown
// or the wire type doesn't match. Put it in our unknown field set.
return SkipField(input, tag,
message_reflection->MutableUnknownFields(message));
}
- switch (field->type()) {
-#define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE, CPPTYPE_METHOD) \
- case FieldDescriptor::TYPE_##TYPE: { \
- CPPTYPE value; \
- if (!Read##TYPE_METHOD(input, &value)) return false; \
- if (field->is_repeated()) { \
- message_reflection->Add##CPPTYPE_METHOD(message, field, value); \
- } else { \
- message_reflection->Set##CPPTYPE_METHOD(message, field, value); \
- } \
- break; \
- }
-
- HANDLE_TYPE( INT32, Int32, int32, Int32)
- HANDLE_TYPE( INT64, Int64, int64, Int64)
- HANDLE_TYPE(SINT32, SInt32, int32, Int32)
- HANDLE_TYPE(SINT64, SInt64, int64, Int64)
- HANDLE_TYPE(UINT32, UInt32, uint32, UInt32)
- HANDLE_TYPE(UINT64, UInt64, uint64, UInt64)
-
- HANDLE_TYPE( FIXED32, Fixed32, uint32, UInt32)
- HANDLE_TYPE( FIXED64, Fixed64, uint64, UInt64)
- HANDLE_TYPE(SFIXED32, SFixed32, int32, Int32)
- HANDLE_TYPE(SFIXED64, SFixed64, int64, Int64)
-
- HANDLE_TYPE(FLOAT , Float , float , Float )
- HANDLE_TYPE(DOUBLE, Double, double, Double)
-
- HANDLE_TYPE(BOOL, Bool, bool, Bool)
-
- HANDLE_TYPE(STRING, String, string, String)
- HANDLE_TYPE(BYTES, Bytes, string, String)
+ if (field->options().packed()) {
+ uint32 length;
+ if (!input->ReadVarint32(&length)) return false;
+ io::CodedInputStream::Limit limit = input->PushLimit(length);
-#undef HANDLE_TYPE
+ switch (field->type()) {
+#define HANDLE_PACKED_TYPE(TYPE, TYPE_METHOD, CPPTYPE, CPPTYPE_METHOD) \
+ case FieldDescriptor::TYPE_##TYPE: { \
+ while (input->BytesUntilLimit() > 0) { \
+ CPPTYPE value; \
+ if (!Read##TYPE_METHOD(input, &value)) return false; \
+ message_reflection->Add##CPPTYPE_METHOD(message, field, value); \
+ } \
+ break; \
+ }
- case FieldDescriptor::TYPE_ENUM: {
- int value;
- if (!ReadEnum(input, &value)) return false;
- const EnumValueDescriptor* enum_value =
- field->enum_type()->FindValueByNumber(value);
- if (enum_value != NULL) {
- if (field->is_repeated()) {
- message_reflection->AddEnum(message, field, enum_value);
- } else {
- message_reflection->SetEnum(message, field, enum_value);
+ HANDLE_PACKED_TYPE( INT32, Int32, int32, Int32)
+ HANDLE_PACKED_TYPE( INT64, Int64, int64, Int64)
+ HANDLE_PACKED_TYPE(SINT32, SInt32, int32, Int32)
+ HANDLE_PACKED_TYPE(SINT64, SInt64, int64, Int64)
+ HANDLE_PACKED_TYPE(UINT32, UInt32, uint32, UInt32)
+ HANDLE_PACKED_TYPE(UINT64, UInt64, uint64, UInt64)
+
+ HANDLE_PACKED_TYPE( FIXED32, Fixed32, uint32, UInt32)
+ HANDLE_PACKED_TYPE( FIXED64, Fixed64, uint64, UInt64)
+ HANDLE_PACKED_TYPE(SFIXED32, SFixed32, int32, Int32)
+ HANDLE_PACKED_TYPE(SFIXED64, SFixed64, int64, Int64)
+
+ HANDLE_PACKED_TYPE(FLOAT , Float , float , Float )
+ HANDLE_PACKED_TYPE(DOUBLE, Double, double, Double)
+
+ HANDLE_PACKED_TYPE(BOOL, Bool, bool, Bool)
+#undef HANDLE_PACKED_TYPE
+
+ case FieldDescriptor::TYPE_ENUM: {
+ while (input->BytesUntilLimit() > 0) {
+ int value;
+ if (!ReadEnum(input, &value)) return false;
+ const EnumValueDescriptor* enum_value =
+ field->enum_type()->FindValueByNumber(value);
+ if (enum_value != NULL) {
+ message_reflection->AddEnum(message, field, enum_value);
+ }
}
- } else {
- // The enum value is not one of the known values. Add it to the
- // UnknownFieldSet.
- int64 sign_extended_value = static_cast<int64>(value);
- message_reflection->MutableUnknownFields(message)
- ->AddField(GetTagFieldNumber(tag))
- ->add_varint(sign_extended_value);
+
+ break;
}
- break;
+
+ case FieldDescriptor::TYPE_STRING:
+ case FieldDescriptor::TYPE_GROUP:
+ case FieldDescriptor::TYPE_MESSAGE:
+ case FieldDescriptor::TYPE_BYTES:
+ // Can't have packed fields of these types: these should be caught by
+ // the protocol compiler.
+ return false;
+ break;
}
+ input->PopLimit(limit);
+ } else {
+ switch (field->type()) {
+#define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE, CPPTYPE_METHOD) \
+ case FieldDescriptor::TYPE_##TYPE: { \
+ CPPTYPE value; \
+ if (!Read##TYPE_METHOD(input, &value)) return false; \
+ if (field->is_repeated()) { \
+ message_reflection->Add##CPPTYPE_METHOD(message, field, value); \
+ } else { \
+ message_reflection->Set##CPPTYPE_METHOD(message, field, value); \
+ } \
+ break; \
+ }
+
+ HANDLE_TYPE( INT32, Int32, int32, Int32)
+ HANDLE_TYPE( INT64, Int64, int64, Int64)
+ HANDLE_TYPE(SINT32, SInt32, int32, Int32)
+ HANDLE_TYPE(SINT64, SInt64, int64, Int64)
+ HANDLE_TYPE(UINT32, UInt32, uint32, UInt32)
+ HANDLE_TYPE(UINT64, UInt64, uint64, UInt64)
- case FieldDescriptor::TYPE_GROUP: {
- Message* sub_message;
- if (field->is_repeated()) {
- sub_message = message_reflection->AddMessage(message, field);
- } else {
- sub_message = message_reflection->MutableMessage(message, field);
+ HANDLE_TYPE( FIXED32, Fixed32, uint32, UInt32)
+ HANDLE_TYPE( FIXED64, Fixed64, uint64, UInt64)
+ HANDLE_TYPE(SFIXED32, SFixed32, int32, Int32)
+ HANDLE_TYPE(SFIXED64, SFixed64, int64, Int64)
+
+ HANDLE_TYPE(FLOAT , Float , float , Float )
+ HANDLE_TYPE(DOUBLE, Double, double, Double)
+
+ HANDLE_TYPE(BOOL, Bool, bool, Bool)
+
+ HANDLE_TYPE(STRING, String, string, String)
+ HANDLE_TYPE(BYTES, Bytes, string, String)
+
+#undef HANDLE_TYPE
+
+ case FieldDescriptor::TYPE_ENUM: {
+ int value;
+ if (!ReadEnum(input, &value)) return false;
+ const EnumValueDescriptor* enum_value =
+ field->enum_type()->FindValueByNumber(value);
+ if (enum_value != NULL) {
+ if (field->is_repeated()) {
+ message_reflection->AddEnum(message, field, enum_value);
+ } else {
+ message_reflection->SetEnum(message, field, enum_value);
+ }
+ } else {
+ // The enum value is not one of the known values. Add it to the
+ // UnknownFieldSet.
+ int64 sign_extended_value = static_cast<int64>(value);
+ message_reflection->MutableUnknownFields(message)
+ ->AddField(GetTagFieldNumber(tag))
+ ->add_varint(sign_extended_value);
+ }
+ break;
}
- if (!ReadGroup(GetTagFieldNumber(tag), input, sub_message)) return false;
- break;
- }
- case FieldDescriptor::TYPE_MESSAGE: {
- Message* sub_message;
- if (field->is_repeated()) {
- sub_message = message_reflection->AddMessage(message, field);
- } else {
- sub_message = message_reflection->MutableMessage(message, field);
+ case FieldDescriptor::TYPE_GROUP: {
+ Message* sub_message;
+ if (field->is_repeated()) {
+ sub_message = message_reflection->AddMessage(message, field);
+ } else {
+ sub_message = message_reflection->MutableMessage(message, field);
+ }
+
+ if (!ReadGroup(GetTagFieldNumber(tag), input, sub_message))
+ return false;
+ break;
}
- if (!ReadMessage(input, sub_message)) return false;
- break;
+ case FieldDescriptor::TYPE_MESSAGE: {
+ Message* sub_message;
+ if (field->is_repeated()) {
+ sub_message = message_reflection->AddMessage(message, field);
+ } else {
+ sub_message = message_reflection->MutableMessage(message, field);
+ }
+
+ if (!ReadMessage(input, sub_message)) return false;
+ break;
+ }
}
}
@@ -602,8 +664,53 @@ bool WireFormat::SerializeFieldWithCachedSizes(
count = 1;
}
+ const bool is_packed = field->options().packed();
+ if (is_packed && count > 0) {
+ if (!WriteTag(field->number(), WIRETYPE_LENGTH_DELIMITED, output))
+ return false;
+ const int data_size = FieldDataOnlyByteSize(field, message);
+ if (!output->WriteVarint32(data_size)) return false;
+ }
+
for (int j = 0; j < count; j++) {
switch (field->type()) {
+#define HANDLE_PRIMITIVE_TYPE(TYPE, CPPTYPE, TYPE_METHOD, CPPTYPE_METHOD) \
+ case FieldDescriptor::TYPE_##TYPE: { \
+ const CPPTYPE value = field->is_repeated() ? \
+ message_reflection->GetRepeated##CPPTYPE_METHOD( \
+ message, field, j) : \
+ message_reflection->Get##CPPTYPE_METHOD( \
+ message, field); \
+ if (is_packed) { \
+ if (!Write##TYPE_METHOD##NoTag(value, output)) { \
+ return false; \
+ } \
+ } else { \
+ if (!Write##TYPE_METHOD(field->number(), value, output)) { \
+ return false; \
+ } \
+ } \
+ break; \
+ }
+
+ HANDLE_PRIMITIVE_TYPE( INT32, int32, Int32, Int32)
+ HANDLE_PRIMITIVE_TYPE( INT64, int64, Int64, Int64)
+ HANDLE_PRIMITIVE_TYPE(SINT32, int32, SInt32, Int32)
+ HANDLE_PRIMITIVE_TYPE(SINT64, int64, SInt64, Int64)
+ HANDLE_PRIMITIVE_TYPE(UINT32, uint32, UInt32, UInt32)
+ HANDLE_PRIMITIVE_TYPE(UINT64, uint64, UInt64, UInt64)
+
+ HANDLE_PRIMITIVE_TYPE( FIXED32, uint32, Fixed32, UInt32)
+ HANDLE_PRIMITIVE_TYPE( FIXED64, uint64, Fixed64, UInt64)
+ HANDLE_PRIMITIVE_TYPE(SFIXED32, int32, SFixed32, Int32)
+ HANDLE_PRIMITIVE_TYPE(SFIXED64, int64, SFixed64, Int64)
+
+ HANDLE_PRIMITIVE_TYPE(FLOAT , float , Float , Float )
+ HANDLE_PRIMITIVE_TYPE(DOUBLE, double, Double, Double)
+
+ HANDLE_PRIMITIVE_TYPE(BOOL, bool, Bool, Bool)
+#undef HANDLE_PRIMITIVE_TYPE
+
#define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE_METHOD) \
case FieldDescriptor::TYPE_##TYPE: \
if (!Write##TYPE_METHOD( \
@@ -617,23 +724,6 @@ bool WireFormat::SerializeFieldWithCachedSizes(
} \
break;
- HANDLE_TYPE( INT32, Int32, Int32)
- HANDLE_TYPE( INT64, Int64, Int64)
- HANDLE_TYPE(SINT32, SInt32, Int32)
- HANDLE_TYPE(SINT64, SInt64, Int64)
- HANDLE_TYPE(UINT32, UInt32, UInt32)
- HANDLE_TYPE(UINT64, UInt64, UInt64)
-
- HANDLE_TYPE( FIXED32, Fixed32, UInt32)
- HANDLE_TYPE( FIXED64, Fixed64, UInt64)
- HANDLE_TYPE(SFIXED32, SFixed32, Int32)
- HANDLE_TYPE(SFIXED64, SFixed64, Int64)
-
- HANDLE_TYPE(FLOAT , Float , Float )
- HANDLE_TYPE(DOUBLE, Double, Double)
-
- HANDLE_TYPE(BOOL, Bool, Bool)
-
HANDLE_TYPE(GROUP , Group , Message)
HANDLE_TYPE(MESSAGE, Message, Message)
#undef HANDLE_TYPE
@@ -642,7 +732,12 @@ bool WireFormat::SerializeFieldWithCachedSizes(
const EnumValueDescriptor* value = field->is_repeated() ?
message_reflection->GetRepeatedEnum(message, field, j) :
message_reflection->GetEnum(message, field);
- if (!WriteEnum(field->number(), value->number(), output)) return false;
+ if (is_packed) {
+ if (!WriteEnumNoTag(value->number(), output)) return false;
+ } else {
+ if (!WriteEnum(field->number(), value->number(), output))
+ return false;
+ }
break;
}
@@ -736,36 +831,60 @@ int WireFormat::FieldByteSize(
return MessageSetItemByteSize(field, message);
}
- int our_size = 0;
-
int count = 0;
-
if (field->is_repeated()) {
count = message_reflection->FieldSize(message, field);
} else if (message_reflection->HasField(message, field)) {
count = 1;
}
- our_size += count * TagSize(field->number(), field->type());
+ const int data_size = FieldDataOnlyByteSize(field, message);
+ int our_size = data_size;
+ if (field->options().packed()) {
+ if (data_size > 0) {
+ // Packed fields get serialized like a string, not their native type.
+ // Technically this doesn't really matter; the size only changes if it's
+ // a GROUP
+ our_size += TagSize(field->number(), FieldDescriptor::TYPE_STRING);
+ our_size += io::CodedOutputStream::VarintSize32(data_size);
+ }
+ } else {
+ our_size += count * TagSize(field->number(), field->type());
+ }
+ return our_size;
+}
+
+int WireFormat::FieldDataOnlyByteSize(
+ const FieldDescriptor* field,
+ const Message& message) {
+ const Reflection* message_reflection = message.GetReflection();
+
+ int count = 0;
+ if (field->is_repeated()) {
+ count = message_reflection->FieldSize(message, field);
+ } else if (message_reflection->HasField(message, field)) {
+ count = 1;
+ }
+ int data_size = 0;
switch (field->type()) {
#define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE_METHOD) \
case FieldDescriptor::TYPE_##TYPE: \
if (field->is_repeated()) { \
for (int j = 0; j < count; j++) { \
- our_size += TYPE_METHOD##Size( \
+ data_size += TYPE_METHOD##Size( \
message_reflection->GetRepeated##CPPTYPE_METHOD( \
message, field, j)); \
} \
} else { \
- our_size += TYPE_METHOD##Size( \
+ data_size += TYPE_METHOD##Size( \
message_reflection->Get##CPPTYPE_METHOD(message, field)); \
} \
break;
#define HANDLE_FIXED_TYPE(TYPE, TYPE_METHOD) \
case FieldDescriptor::TYPE_##TYPE: \
- our_size += count * k##TYPE_METHOD##Size; \
+ data_size += count * k##TYPE_METHOD##Size; \
break;
HANDLE_TYPE( INT32, Int32, Int32)
@@ -793,11 +912,11 @@ int WireFormat::FieldByteSize(
case FieldDescriptor::TYPE_ENUM: {
if (field->is_repeated()) {
for (int j = 0; j < count; j++) {
- our_size += EnumSize(
+ data_size += EnumSize(
message_reflection->GetRepeatedEnum(message, field, j)->number());
}
} else {
- our_size += EnumSize(
+ data_size += EnumSize(
message_reflection->GetEnum(message, field)->number());
}
break;
@@ -813,13 +932,12 @@ int WireFormat::FieldByteSize(
message_reflection->GetRepeatedStringReference(
message, field, j, &scratch) :
message_reflection->GetStringReference(message, field, &scratch);
- our_size += StringSize(value);
+ data_size += StringSize(value);
}
break;
}
}
-
- return our_size;
+ return data_size;
}
int WireFormat::MessageSetItemByteSize(
diff --git a/src/google/protobuf/wire_format.h b/src/google/protobuf/wire_format.h
index 06f20d2a..9004caaa 100644
--- a/src/google/protobuf/wire_format.h
+++ b/src/google/protobuf/wire_format.h
@@ -163,13 +163,20 @@ class LIBPROTOBUF_EXPORT WireFormat {
static inline WireType WireTypeForFieldType(FieldDescriptor::Type type) {
return kWireTypeForFieldType[type];
}
+ // This is different from WireTypeForFieldType(field->type()) in the case of
+ // packed repeated fields.
+ static inline WireType WireTypeForField(const FieldDescriptor* field);
// Number of bits in a tag which identify the wire type.
static const int kTagTypeBits = 3;
// Mask for those bits.
static const uint32 kTagTypeMask = (1 << kTagTypeBits) - 1;
- // Helper functions for encoding and decoding tags. (Inlined below.)
+ // Helper functions for encoding and decoding tags. (Inlined below and in
+ // _inl.h)
+ //
+ // This is different from MakeTag(field->number(), field->type()) in the case
+ // of packed repeated fields.
static uint32 MakeTag(const FieldDescriptor* field);
static uint32 MakeTag(int field_number, WireType type);
static WireType GetTagWireType(uint32 tag);
@@ -258,10 +265,27 @@ class LIBPROTOBUF_EXPORT WireFormat {
template<typename MessageType>
static inline bool ReadMessageNoVirtual(input, MessageType* value);
- // Write a tag. The Write*() functions automatically include the tag, so
- // normally there's no need to call this.
+ // Write a tag. The Write*() functions typically include the tag, so
+ // normally there's no need to call this unless using the Write*NoTag()
+ // variants.
static inline bool WriteTag(field_number, WireType type, output) INL;
+ // Write fields, without tags.
+ static inline bool WriteInt32NoTag (int32 value, output) INL;
+ static inline bool WriteInt64NoTag (int64 value, output) INL;
+ static inline bool WriteUInt32NoTag (uint32 value, output) INL;
+ static inline bool WriteUInt64NoTag (uint64 value, output) INL;
+ static inline bool WriteSInt32NoTag (int32 value, output) INL;
+ static inline bool WriteSInt64NoTag (int64 value, output) INL;
+ static inline bool WriteFixed32NoTag (uint32 value, output) INL;
+ static inline bool WriteFixed64NoTag (uint64 value, output) INL;
+ static inline bool WriteSFixed32NoTag(int32 value, output) INL;
+ static inline bool WriteSFixed64NoTag(int64 value, output) INL;
+ static inline bool WriteFloatNoTag (float value, output) INL;
+ static inline bool WriteDoubleNoTag (double value, output) INL;
+ static inline bool WriteBoolNoTag (bool value, output) INL;
+ static inline bool WriteEnumNoTag (int value, output) INL;
+
// Write fields, including tags.
static inline bool WriteInt32 (field_number, int32 value, output) INL;
static inline bool WriteInt64 (field_number, int64 value, output) INL;
@@ -355,6 +379,14 @@ class LIBPROTOBUF_EXPORT WireFormat {
const FieldDescriptor* field,
const Message& message);
+ // Computes the byte size of a field, excluding tags. For packed fields, it
+ // only includes the size of the raw data, and not the size of the total
+ // length, but for other length-delimited types, the size of the length is
+ // included.
+ static int FieldDataOnlyByteSize(
+ const FieldDescriptor* field, // Cannot be NULL
+ const Message& message);
+
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WireFormat);
};
@@ -368,10 +400,6 @@ class LIBPROTOBUF_EXPORT WireFormat {
static_cast<uint32>( \
((FIELD_NUMBER) << ::google::protobuf::internal::WireFormat::kTagTypeBits) | (TYPE))
-inline uint32 WireFormat::MakeTag(const FieldDescriptor* field) {
- return MakeTag(field->number(), WireTypeForFieldType(field->type()));
-}
-
inline uint32 WireFormat::MakeTag(int field_number, WireType type) {
return GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(field_number, type);
}
diff --git a/src/google/protobuf/wire_format_inl.h b/src/google/protobuf/wire_format_inl.h
index 539d8c67..451ac11c 100644
--- a/src/google/protobuf/wire_format_inl.h
+++ b/src/google/protobuf/wire_format_inl.h
@@ -38,6 +38,8 @@
#include <string>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/wire_format.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/coded_stream.h>
@@ -51,6 +53,19 @@ namespace google {
namespace protobuf {
namespace internal {
+inline WireFormat::WireType WireFormat::WireTypeForField(
+ const FieldDescriptor* field) {
+ if (field->options().packed()) {
+ return WIRETYPE_LENGTH_DELIMITED;
+ } else {
+ return WireTypeForFieldType(field->type());
+ }
+}
+
+inline uint32 WireFormat::MakeTag(const FieldDescriptor* field) {
+ return MakeTag(field->number(), WireTypeForField(field));
+}
+
inline bool WireFormat::ReadInt32(io::CodedInputStream* input, int32* value) {
uint32 temp;
if (!input->ReadVarint32(&temp)) return false;
@@ -210,75 +225,132 @@ inline bool WireFormat::WriteTag(int field_number, WireType type,
return output->WriteTag(MakeTag(field_number, type));
}
+inline bool WireFormat::WriteInt32NoTag(int32 value,
+ io::CodedOutputStream* output) {
+ return output->WriteVarint32SignExtended(value);
+}
+inline bool WireFormat::WriteInt64NoTag(int64 value,
+ io::CodedOutputStream* output) {
+ return output->WriteVarint64(static_cast<uint64>(value));
+}
+inline bool WireFormat::WriteUInt32NoTag(uint32 value,
+ io::CodedOutputStream* output) {
+ return output->WriteVarint32(value);
+}
+inline bool WireFormat::WriteUInt64NoTag(uint64 value,
+ io::CodedOutputStream* output) {
+ return output->WriteVarint64(value);
+}
+inline bool WireFormat::WriteSInt32NoTag(int32 value,
+ io::CodedOutputStream* output) {
+ return output->WriteVarint32(ZigZagEncode32(value));
+}
+inline bool WireFormat::WriteSInt64NoTag(int64 value,
+ io::CodedOutputStream* output) {
+ return output->WriteVarint64(ZigZagEncode64(value));
+}
+inline bool WireFormat::WriteFixed32NoTag(uint32 value,
+ io::CodedOutputStream* output) {
+ return output->WriteLittleEndian32(value);
+}
+inline bool WireFormat::WriteFixed64NoTag(uint64 value,
+ io::CodedOutputStream* output) {
+ return output->WriteLittleEndian64(value);
+}
+inline bool WireFormat::WriteSFixed32NoTag(int32 value,
+ io::CodedOutputStream* output) {
+ return output->WriteLittleEndian32(static_cast<uint32>(value));
+}
+inline bool WireFormat::WriteSFixed64NoTag(int64 value,
+ io::CodedOutputStream* output) {
+ return output->WriteLittleEndian64(static_cast<uint64>(value));
+}
+inline bool WireFormat::WriteFloatNoTag(float value,
+ io::CodedOutputStream* output) {
+ return output->WriteLittleEndian32(EncodeFloat(value));
+}
+inline bool WireFormat::WriteDoubleNoTag(double value,
+ io::CodedOutputStream* output) {
+ return output->WriteLittleEndian64(EncodeDouble(value));
+}
+inline bool WireFormat::WriteBoolNoTag(bool value,
+ io::CodedOutputStream* output) {
+ return output->WriteVarint32(value ? 1 : 0);
+}
+inline bool WireFormat::WriteEnumNoTag(int value,
+ io::CodedOutputStream* output) {
+ return output->WriteVarint32SignExtended(value);
+}
+
inline bool WireFormat::WriteInt32(int field_number, int32 value,
io::CodedOutputStream* output) {
return WriteTag(field_number, WIRETYPE_VARINT, output) &&
- output->WriteVarint32SignExtended(value);
+ WriteInt32NoTag(value, output);
}
inline bool WireFormat::WriteInt64(int field_number, int64 value,
io::CodedOutputStream* output) {
return WriteTag(field_number, WIRETYPE_VARINT, output) &&
- output->WriteVarint64(static_cast<uint64>(value));
+ WriteInt64NoTag(value, output);
}
inline bool WireFormat::WriteUInt32(int field_number, uint32 value,
io::CodedOutputStream* output) {
return WriteTag(field_number, WIRETYPE_VARINT, output) &&
- output->WriteVarint32(value);
+ WriteUInt32NoTag(value, output);
}
inline bool WireFormat::WriteUInt64(int field_number, uint64 value,
io::CodedOutputStream* output) {
return WriteTag(field_number, WIRETYPE_VARINT, output) &&
- output->WriteVarint64(value);
+ WriteUInt64NoTag(value, output);
}
inline bool WireFormat::WriteSInt32(int field_number, int32 value,
io::CodedOutputStream* output) {
return WriteTag(field_number, WIRETYPE_VARINT, output) &&
- output->WriteVarint32(ZigZagEncode32(value));
+ WriteSInt32NoTag(value, output);
}
inline bool WireFormat::WriteSInt64(int field_number, int64 value,
io::CodedOutputStream* output) {
return WriteTag(field_number, WIRETYPE_VARINT, output) &&
- output->WriteVarint64(ZigZagEncode64(value));
+ WriteSInt64NoTag(value, output);
}
inline bool WireFormat::WriteFixed32(int field_number, uint32 value,
io::CodedOutputStream* output) {
return WriteTag(field_number, WIRETYPE_FIXED32, output) &&
- output->WriteLittleEndian32(value);
+ WriteFixed32NoTag(value, output);
}
inline bool WireFormat::WriteFixed64(int field_number, uint64 value,
io::CodedOutputStream* output) {
return WriteTag(field_number, WIRETYPE_FIXED64, output) &&
- output->WriteLittleEndian64(value);
+ WriteFixed64NoTag(value, output);
}
inline bool WireFormat::WriteSFixed32(int field_number, int32 value,
io::CodedOutputStream* output) {
return WriteTag(field_number, WIRETYPE_FIXED32, output) &&
- output->WriteLittleEndian32(static_cast<uint32>(value));
+ WriteSFixed32NoTag(value, output);
}
inline bool WireFormat::WriteSFixed64(int field_number, int64 value,
io::CodedOutputStream* output) {
return WriteTag(field_number, WIRETYPE_FIXED64, output) &&
- output->WriteLittleEndian64(static_cast<uint64>(value));
+ WriteSFixed64NoTag(value, output);
}
inline bool WireFormat::WriteFloat(int field_number, float value,
io::CodedOutputStream* output) {
return WriteTag(field_number, WIRETYPE_FIXED32, output) &&
- output->WriteLittleEndian32(EncodeFloat(value));
+ WriteFloatNoTag(value, output);
}
inline bool WireFormat::WriteDouble(int field_number, double value,
io::CodedOutputStream* output) {
return WriteTag(field_number, WIRETYPE_FIXED64, output) &&
- output->WriteLittleEndian64(EncodeDouble(value));
+ WriteDoubleNoTag(value, output);
}
inline bool WireFormat::WriteBool(int field_number, bool value,
io::CodedOutputStream* output) {
return WriteTag(field_number, WIRETYPE_VARINT, output) &&
- output->WriteVarint32(value ? 1 : 0);
+ WriteBoolNoTag(value, output);
}
inline bool WireFormat::WriteEnum(int field_number, int value,
io::CodedOutputStream* output) {
return WriteTag(field_number, WIRETYPE_VARINT, output) &&
- output->WriteVarint32SignExtended(value);
+ WriteEnumNoTag(value, output);
}
inline bool WireFormat::WriteString(int field_number, const string& value,
diff --git a/src/google/protobuf/wire_format_unittest.cc b/src/google/protobuf/wire_format_unittest.cc
index 43dccd1a..5a7c6c23 100644
--- a/src/google/protobuf/wire_format_unittest.cc
+++ b/src/google/protobuf/wire_format_unittest.cc
@@ -90,6 +90,40 @@ TEST(WireFormatTest, ParseExtensions) {
TestUtil::ExpectAllExtensionsSet(dest);
}
+TEST(WireFormatTest, ParsePacked) {
+ unittest::TestPackedTypes source, dest;
+ string data;
+
+ // Serialize using the generated code.
+ TestUtil::SetPackedFields(&source);
+ source.SerializeToString(&data);
+
+ // Parse using WireFormat.
+ io::ArrayInputStream raw_input(data.data(), data.size());
+ io::CodedInputStream input(&raw_input);
+ WireFormat::ParseAndMergePartial(&input, &dest);
+
+ // Check.
+ TestUtil::ExpectPackedFieldsSet(dest);
+}
+
+TEST(WireFormatTest, ParsePackedExtensions) {
+ unittest::TestPackedExtensions source, dest;
+ string data;
+
+ // Serialize using the generated code.
+ TestUtil::SetPackedExtensions(&source);
+ source.SerializeToString(&data);
+
+ // Parse using WireFormat.
+ io::ArrayInputStream raw_input(data.data(), data.size());
+ io::CodedInputStream input(&raw_input);
+ WireFormat::ParseAndMergePartial(&input, &dest);
+
+ // Check.
+ TestUtil::ExpectPackedExtensionsSet(dest);
+}
+
TEST(WireFormatTest, ByteSize) {
unittest::TestAllTypes message;
TestUtil::SetAllFields(&message);
@@ -111,6 +145,27 @@ TEST(WireFormatTest, ByteSizeExtensions) {
EXPECT_EQ(0, WireFormat::ByteSize(message));
}
+TEST(WireFormatTest, ByteSizePacked) {
+ unittest::TestPackedTypes message;
+ TestUtil::SetPackedFields(&message);
+
+ EXPECT_EQ(message.ByteSize(), WireFormat::ByteSize(message));
+ message.Clear();
+ EXPECT_EQ(0, message.ByteSize());
+ EXPECT_EQ(0, WireFormat::ByteSize(message));
+}
+
+TEST(WireFormatTest, ByteSizePackedExtensions) {
+ unittest::TestPackedExtensions message;
+ TestUtil::SetPackedExtensions(&message);
+
+ EXPECT_EQ(message.ByteSize(),
+ WireFormat::ByteSize(message));
+ message.Clear();
+ EXPECT_EQ(0, message.ByteSize());
+ EXPECT_EQ(0, WireFormat::ByteSize(message));
+}
+
TEST(WireFormatTest, Serialize) {
unittest::TestAllTypes message;
string generated_data;