Align with main: two ways of parsing repeated packable fields.

It is a requirement for parsing code to handle packed and unpacked
forms on the wire for repeated packable fields. This change aligns
the javanano's behavior with the java's.

Bonus: optimize array length calculation when parsing repeated
fixed-size-element-type fields.

Bonus 2: lose "xMemoizedSerializedSize" for repeated enum fields,
and make the serialized size calculation match that for repeated
int32 fields.

Change-Id: I8a06103d9290234adb46b0971b5ed155544fe86a
pull/91/head
Max Cai 11 years ago
parent 190edd7ef6
commit adf2449a6d
  1. 1
      java/README.txt
  2. 72
      java/src/test/java/com/google/protobuf/NanoTest.java
  3. 132
      src/google/protobuf/compiler/javanano/javanano_enum_field.cc
  4. 3
      src/google/protobuf/compiler/javanano/javanano_enum_field.h
  5. 10
      src/google/protobuf/compiler/javanano/javanano_field.cc
  6. 6
      src/google/protobuf/compiler/javanano/javanano_field.h
  7. 20
      src/google/protobuf/compiler/javanano/javanano_message.cc
  8. 91
      src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
  9. 1
      src/google/protobuf/compiler/javanano/javanano_primitive_field.h
  10. 95
      src/google/protobuf/unittest_repeated_packables_nano.proto

@ -429,6 +429,7 @@ Except:
- Similar rename from CodedOutputStreamMicro to
CodedOutputByteBufferNano.
- Repeated fields are in arrays, not ArrayList or Vector.
- Full support of serializing/deserializing repeated packed fields.
- Unset messages/groups are null, not an immutable empty default
instance.
- Required fields are always serialized.

@ -49,6 +49,7 @@ import com.google.protobuf.nano.NanoHasOuterClass.TestAllTypesNanoHas;
import com.google.protobuf.nano.NanoOuterClass;
import com.google.protobuf.nano.NanoOuterClass.TestAllTypesNano;
import com.google.protobuf.nano.NanoReferenceTypes;
import com.google.protobuf.nano.NanoRepeatedPackables;
import com.google.protobuf.nano.TestRepeatedMergeNano;
import com.google.protobuf.nano.UnittestImportNano;
import com.google.protobuf.nano.UnittestMultipleNano;
@ -3064,6 +3065,77 @@ public class NanoTest extends TestCase {
assertEquals(30, firstContainer.contained.repeatedInt32[2]);
}
public void testRepeatedPackables() throws Exception {
// Check that repeated fields with packable types can accept both packed and unpacked
// serialized forms.
NanoRepeatedPackables.NonPacked nonPacked = new NanoRepeatedPackables.NonPacked();
nonPacked.int32S = new int[] {1, 2, 3};
nonPacked.int64S = new long[] {4, 5, 6};
nonPacked.uint32S = new int[] {7, 8, 9};
nonPacked.uint64S = new long[] {10, 11, 12};
nonPacked.sint32S = new int[] {13, 14, 15};
nonPacked.sint64S = new long[] {16, 17, 18};
nonPacked.fixed32S = new int[] {19, 20, 21};
nonPacked.fixed64S = new long[] {22, 23, 24};
nonPacked.sfixed32S = new int[] {25, 26, 27};
nonPacked.sfixed64S = new long[] {28, 29, 30};
nonPacked.floats = new float[] {31, 32, 33};
nonPacked.doubles = new double[] {34, 35, 36};
nonPacked.bools = new boolean[] {false, true};
nonPacked.enums = new int[] {
NanoRepeatedPackables.Enum.OPTION_ONE,
NanoRepeatedPackables.Enum.OPTION_TWO,
};
nonPacked.noise = 13579;
byte[] nonPackedSerialized = MessageNano.toByteArray(nonPacked);
NanoRepeatedPackables.Packed packed =
MessageNano.mergeFrom(new NanoRepeatedPackables.Packed(), nonPackedSerialized);
assertRepeatedPackablesEqual(nonPacked, packed);
byte[] packedSerialized = MessageNano.toByteArray(packed);
// Just a cautious check that the two serialized forms are different,
// to make sure the remaining of this test is useful:
assertFalse(Arrays.equals(nonPackedSerialized, packedSerialized));
nonPacked = MessageNano.mergeFrom(new NanoRepeatedPackables.NonPacked(), packedSerialized);
assertRepeatedPackablesEqual(nonPacked, packed);
// Test mixed serialized form.
byte[] mixedSerialized = new byte[nonPackedSerialized.length + packedSerialized.length];
System.arraycopy(nonPackedSerialized, 0, mixedSerialized, 0, nonPackedSerialized.length);
System.arraycopy(packedSerialized, 0,
mixedSerialized, nonPackedSerialized.length, packedSerialized.length);
nonPacked = MessageNano.mergeFrom(new NanoRepeatedPackables.NonPacked(), mixedSerialized);
packed = MessageNano.mergeFrom(new NanoRepeatedPackables.Packed(), mixedSerialized);
assertRepeatedPackablesEqual(nonPacked, packed);
assertTrue(Arrays.equals(new int[] {1, 2, 3, 1, 2, 3}, nonPacked.int32S));
assertTrue(Arrays.equals(new int[] {13, 14, 15, 13, 14, 15}, nonPacked.sint32S));
assertTrue(Arrays.equals(new int[] {25, 26, 27, 25, 26, 27}, nonPacked.sfixed32S));
assertTrue(Arrays.equals(new boolean[] {false, true, false, true}, nonPacked.bools));
}
private void assertRepeatedPackablesEqual(
NanoRepeatedPackables.NonPacked nonPacked, NanoRepeatedPackables.Packed packed) {
// Not using MessageNano.equals() -- that belongs to a separate test.
assertTrue(Arrays.equals(nonPacked.int32S, packed.int32S));
assertTrue(Arrays.equals(nonPacked.int64S, packed.int64S));
assertTrue(Arrays.equals(nonPacked.uint32S, packed.uint32S));
assertTrue(Arrays.equals(nonPacked.uint64S, packed.uint64S));
assertTrue(Arrays.equals(nonPacked.sint32S, packed.sint32S));
assertTrue(Arrays.equals(nonPacked.sint64S, packed.sint64S));
assertTrue(Arrays.equals(nonPacked.fixed32S, packed.fixed32S));
assertTrue(Arrays.equals(nonPacked.fixed64S, packed.fixed64S));
assertTrue(Arrays.equals(nonPacked.sfixed32S, packed.sfixed32S));
assertTrue(Arrays.equals(nonPacked.sfixed64S, packed.sfixed64S));
assertTrue(Arrays.equals(nonPacked.floats, packed.floats));
assertTrue(Arrays.equals(nonPacked.doubles, packed.doubles));
assertTrue(Arrays.equals(nonPacked.bools, packed.bools));
assertTrue(Arrays.equals(nonPacked.enums, packed.enums));
}
private void assertHasWireData(MessageNano message, boolean expected) {
byte[] bytes = MessageNano.toByteArray(message);
int wireLength = bytes.length;

@ -294,10 +294,6 @@ void RepeatedEnumFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"public $type$[] $name$;\n");
if (descriptor_->options().packed()) {
printer->Print(variables_,
"private int $name$MemoizedSerializedSize;\n");
}
}
void RepeatedEnumFieldGenerator::
@ -309,45 +305,58 @@ GenerateClearCode(io::Printer* printer) const {
void RepeatedEnumFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
// First, figure out the length of the array, then parse.
if (descriptor_->options().packed()) {
printer->Print(variables_,
"int length = input.readRawVarint32();\n"
"int limit = input.pushLimit(length);\n"
"// First pass to compute array length.\n"
"int arrayLength = 0;\n"
"int startPos = input.getPosition();\n"
"while (input.getBytesUntilLimit() > 0) {\n"
" input.readInt32();\n"
" arrayLength++;\n"
"}\n"
"input.rewindToPosition(startPos);\n"
"int i = this.$name$ == null ? 0 : this.$name$.length;\n"
"int[] newArray = new int[i + arrayLength];\n"
"if (i != 0) {\n"
" java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
"}\n"
"for (; i < newArray.length; i++) {\n"
" newArray[i] = input.readInt32();\n"
"}\n"
"this.$name$ = newArray;\n"
"input.popLimit(limit);\n");
} else {
printer->Print(variables_,
"int arrayLength = com.google.protobuf.nano.WireFormatNano\n"
" .getRepeatedFieldArrayLength(input, $tag$);\n"
"int i = this.$name$ == null ? 0 : this.$name$.length;\n"
"int[] newArray = new int[i + arrayLength];\n"
"if (i != 0) {\n"
" java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
"}\n"
"for (; i < newArray.length - 1; i++) {\n"
" newArray[i] = input.readInt32();\n"
" input.readTag();\n"
"}\n"
"// Last one without readTag.\n"
"newArray[i] = input.readInt32();\n"
"this.$name$ = newArray;\n");
}
printer->Print(variables_,
"int arrayLength = com.google.protobuf.nano.WireFormatNano\n"
" .getRepeatedFieldArrayLength(input, $tag$);\n"
"int i = this.$name$ == null ? 0 : this.$name$.length;\n"
"int[] newArray = new int[i + arrayLength];\n"
"if (i != 0) {\n"
" java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
"}\n"
"for (; i < newArray.length - 1; i++) {\n"
" newArray[i] = input.readInt32();\n"
" input.readTag();\n"
"}\n"
"// Last one without readTag.\n"
"newArray[i] = input.readInt32();\n"
"this.$name$ = newArray;\n");
}
void RepeatedEnumFieldGenerator::
GenerateMergingCodeFromPacked(io::Printer* printer) const {
printer->Print(variables_,
"int length = input.readRawVarint32();\n"
"int limit = input.pushLimit(length);\n"
"// First pass to compute array length.\n"
"int arrayLength = 0;\n"
"int startPos = input.getPosition();\n"
"while (input.getBytesUntilLimit() > 0) {\n"
" input.readInt32();\n"
" arrayLength++;\n"
"}\n"
"input.rewindToPosition(startPos);\n"
"int i = this.$name$ == null ? 0 : this.$name$.length;\n"
"int[] newArray = new int[i + arrayLength];\n"
"if (i != 0) {\n"
" java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
"}\n"
"for (; i < newArray.length; i++) {\n"
" newArray[i] = input.readInt32();\n"
"}\n"
"this.$name$ = newArray;\n"
"input.popLimit(limit);\n");
}
void RepeatedEnumFieldGenerator::
GenerateRepeatedDataSizeCode(io::Printer* printer) const {
// Creates a variable dataSize and puts the serialized size in there.
printer->Print(variables_,
"int dataSize = 0;\n"
"for (int i = 0; i < this.$name$.length; i++) {\n"
" int element = this.$name$[i];\n"
" dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .computeInt32SizeNoTag(element);\n"
"}\n");
}
void RepeatedEnumFieldGenerator::
@ -357,18 +366,20 @@ GenerateSerializationCode(io::Printer* printer) const {
printer->Indent();
if (descriptor_->options().packed()) {
GenerateRepeatedDataSizeCode(printer);
printer->Print(variables_,
"output.writeRawVarint32($tag$);\n"
"output.writeRawVarint32($name$MemoizedSerializedSize);\n"
"for (int element : this.$name$) {\n"
" output.writeRawVarint32(element);\n"
"output.writeRawVarint32(dataSize);\n"
"for (int i = 0; i < this.$name$.length; i++) {\n"
" output.writeRawVarint32(this.$name$[i]);\n"
"}\n");
} else {
printer->Print(variables_,
"for (int element : this.$name$) {\n"
" output.writeInt32($number$, element);\n"
"for (int i = 0; i < this.$name$.length; i++) {\n"
" output.writeInt32($number$, this.$name$[i]);\n"
"}\n");
}
printer->Outdent();
printer->Print(variables_,
"}\n");
@ -380,39 +391,24 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
"if (this.$name$ != null && this.$name$.length > 0) {\n");
printer->Indent();
printer->Print(variables_,
"int dataSize = 0;\n"
"for (int element : this.$name$) {\n"
" dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .computeInt32SizeNoTag(element);\n"
"}\n");
GenerateRepeatedDataSizeCode(printer);
printer->Print(
"size += dataSize;\n");
if (descriptor_->options().packed()) {
// cache the data size for packed fields.
printer->Print(variables_,
"size += $tag_size$;\n"
"size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .computeRawVarint32Size(dataSize);\n"
"$name$MemoizedSerializedSize = dataSize;\n");
" .computeRawVarint32Size(dataSize);\n");
} else {
printer->Print(variables_,
"size += $tag_size$ * this.$name$.length;\n");
"size += $tag_size$ * this.$name$.length;\n");
}
printer->Outdent();
// set cached size to 0 for empty packed fields.
if (descriptor_->options().packed()) {
printer->Print(variables_,
"} else {\n"
" $name$MemoizedSerializedSize = 0;\n"
"}\n");
} else {
printer->Print(
"}\n");
}
printer->Print(
"}\n");
}
void RepeatedEnumFieldGenerator::

@ -96,12 +96,15 @@ class RepeatedEnumFieldGenerator : public FieldGenerator {
void GenerateMembers(io::Printer* printer) const;
void GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateMergingCodeFromPacked(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
void GenerateEqualsCode(io::Printer* printer) const;
void GenerateHashCodeCode(io::Printer* printer) const;
private:
void GenerateRepeatedDataSizeCode(io::Printer* printer) const;
const FieldDescriptor* descriptor_;
map<string, string> variables_;

@ -46,6 +46,16 @@ namespace javanano {
FieldGenerator::~FieldGenerator() {}
void FieldGenerator::GenerateMergingCodeFromPacked(io::Printer* printer) const {
// Reaching here indicates a bug. Cases are:
// - This FieldGenerator should support packing, but this method should be
// overridden.
// - This FieldGenerator doesn't support packing, and this method should
// never have been called.
GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() "
<< "called on field generator that does not support packing.";
}
FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor, const Params &params)
: descriptor_(descriptor),
field_generators_(

@ -60,6 +60,12 @@ class FieldGenerator {
virtual void GenerateMembers(io::Printer* printer) const = 0;
virtual void GenerateClearCode(io::Printer* printer) const = 0;
virtual void GenerateMergingCode(io::Printer* printer) const = 0;
// Generates code to merge from packed serialized form. The default
// implementation will fail; subclasses which can handle packed serialized
// forms will override this and print appropriate code to the printer.
virtual void GenerateMergingCodeFromPacked(io::Printer* printer) const;
virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
virtual void GenerateEqualsCode(io::Printer* printer) const = 0;

@ -320,7 +320,7 @@ void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = sorted_fields[i];
uint32 tag = WireFormatLite::MakeTag(field->number(),
WireFormat::WireTypeForField(field));
WireFormat::WireTypeForFieldType(field->type()));
printer->Print(
"case $tag$: {\n",
@ -333,6 +333,24 @@ void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {
printer->Print(
" break;\n"
"}\n");
if (field->is_packable()) {
// To make packed = true wire compatible, we generate parsing code from a
// packed version of this field regardless of field->options().packed().
uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
printer->Print(
"case $tag$: {\n",
"tag", SimpleItoa(packed_tag));
printer->Indent();
field_generators_.get(field).GenerateMergingCodeFromPacked(printer);
printer->Outdent();
printer->Print(
" break;\n"
"}\n");
}
}
printer->Outdent();

@ -685,10 +685,46 @@ GenerateClearCode(io::Printer* printer) const {
void RepeatedPrimitiveFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
// First, figure out the length of the array, then parse.
if (descriptor_->is_packable() && descriptor_->options().packed()) {
printer->Print(variables_,
"int arrayLength = com.google.protobuf.nano.WireFormatNano\n"
" .getRepeatedFieldArrayLength(input, $tag$);\n"
"int i = this.$name$ == null ? 0 : this.$name$.length;\n");
if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
printer->Print(variables_,
"byte[][] newArray = new byte[i + arrayLength][];\n");
} else {
printer->Print(variables_,
"$type$[] newArray = new $type$[i + arrayLength];\n");
}
printer->Print(variables_,
"if (i != 0) {\n"
" java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
"}\n"
"for (; i < newArray.length - 1; i++) {\n"
" newArray[i] = input.read$capitalized_type$();\n"
" input.readTag();\n"
"}\n"
"// Last one without readTag.\n"
"newArray[i] = input.read$capitalized_type$();\n"
"this.$name$ = newArray;\n");
}
void RepeatedPrimitiveFieldGenerator::
GenerateMergingCodeFromPacked(io::Printer* printer) const {
printer->Print(
"int length = input.readRawVarint32();\n"
"int limit = input.pushLimit(length);\n");
// If we know the elements will all be of the same size, the arrayLength
// can be calculated much more easily. However, FixedSize() returns 1 for
// repeated bool fields, which are guaranteed to have the fixed size of
// 1 byte per value only if we control the output. On the wire they can
// legally appear as variable-size integers, so we need to use the slow
// way for repeated bool fields.
if (descriptor_->type() == FieldDescriptor::TYPE_BOOL
|| FixedSize(descriptor_->type()) == -1) {
printer->Print(variables_,
"int length = input.readRawVarint32();\n"
"int limit = input.pushLimit(length);\n"
"// First pass to compute array length.\n"
"int arrayLength = 0;\n"
"int startPos = input.getPosition();\n"
@ -696,42 +732,23 @@ GenerateMergingCode(io::Printer* printer) const {
" input.read$capitalized_type$();\n"
" arrayLength++;\n"
"}\n"
"input.rewindToPosition(startPos);\n"
"int i = this.$name$ == null ? 0 : this.$name$.length;\n"
"$type$[] newArray = new $type$[i + arrayLength];\n"
"if (i != 0) {\n"
" java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
"}\n"
"for (; i < newArray.length; i++) {\n"
" newArray[i] = input.read$capitalized_type$();\n"
"}\n"
"this.$name$ = newArray;\n"
"input.popLimit(limit);\n");
"input.rewindToPosition(startPos);\n");
} else {
printer->Print(variables_,
"int arrayLength = com.google.protobuf.nano.WireFormatNano\n"
" .getRepeatedFieldArrayLength(input, $tag$);\n"
"int i = this.$name$ == null ? 0 : this.$name$.length;\n");
if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
printer->Print(variables_,
"byte[][] newArray = new byte[i + arrayLength][];\n");
} else {
printer->Print(variables_,
"$type$[] newArray = new $type$[i + arrayLength];\n");
}
printer->Print(variables_,
"if (i != 0) {\n"
" java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
"}\n"
"for (; i < newArray.length - 1; i++) {\n"
" newArray[i] = input.read$capitalized_type$();\n"
" input.readTag();\n"
"}\n"
"// Last one without readTag.\n"
"newArray[i] = input.read$capitalized_type$();\n"
"this.$name$ = newArray;\n");
"int arrayLength = length / $fixed_size$;\n");
}
printer->Print(variables_,
"int i = this.$name$ == null ? 0 : this.$name$.length;\n"
"$type$[] newArray = new $type$[i + arrayLength];\n"
"if (i != 0) {\n"
" java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
"}\n"
"for (; i < newArray.length; i++) {\n"
" newArray[i] = input.read$capitalized_type$();\n"
"}\n"
"this.$name$ = newArray;\n"
"input.popLimit(limit);\n");
}
void RepeatedPrimitiveFieldGenerator::
@ -812,7 +829,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"size += $tag_size$;\n"
"size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .computeRawVarint32Size(dataSize);\n");
" .computeRawVarint32Size(dataSize);\n");
} else if (IsReferenceType(GetJavaType(descriptor_))) {
printer->Print(variables_,
"size += $tag_size$ * dataCount;\n");

@ -98,6 +98,7 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
void GenerateMembers(io::Printer* printer) const;
void GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateMergingCodeFromPacked(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
void GenerateEqualsCode(io::Printer* printer) const;

@ -0,0 +1,95 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: maxtroy@google.com (Max Cai)
package protobuf_unittest;
option java_package = "com.google.protobuf.nano";
option java_outer_classname = "NanoRepeatedPackables";
enum Enum {
OPTION_ONE = 1;
OPTION_TWO = 2;
}
// Two almost identical messages with all packable repeated field types.
// One with none marked as packed and the other all packed. For
// compatibility, they should be able to parse each other's serialized
// forms.
message NonPacked {
// All packable types, none marked as packed.
repeated int32 int32s = 1;
repeated int64 int64s = 2;
repeated uint32 uint32s = 3;
repeated uint64 uint64s = 4;
repeated sint32 sint32s = 5;
repeated sint64 sint64s = 6;
repeated fixed32 fixed32s = 7;
repeated fixed64 fixed64s = 8;
repeated sfixed32 sfixed32s = 9;
repeated sfixed64 sfixed64s = 10;
repeated float floats = 11;
repeated double doubles = 12;
repeated bool bools = 13;
repeated Enum enums = 14;
// Noise for testing merged deserialization.
optional int32 noise = 15;
}
message Packed {
// All packable types, all matching the field numbers in NonPacked,
// all marked as packed.
repeated int32 int32s = 1 [ packed = true ];
repeated int64 int64s = 2 [ packed = true ];
repeated uint32 uint32s = 3 [ packed = true ];
repeated uint64 uint64s = 4 [ packed = true ];
repeated sint32 sint32s = 5 [ packed = true ];
repeated sint64 sint64s = 6 [ packed = true ];
repeated fixed32 fixed32s = 7 [ packed = true ];
repeated fixed64 fixed64s = 8 [ packed = true ];
repeated sfixed32 sfixed32s = 9 [ packed = true ];
repeated sfixed64 sfixed64s = 10 [ packed = true ];
repeated float floats = 11 [ packed = true ];
repeated double doubles = 12 [ packed = true ];
repeated bool bools = 13 [ packed = true ];
repeated Enum enums = 14 [ packed = true ];
// Noise for testing merged deserialization.
optional int32 noise = 15;
}
Loading…
Cancel
Save