Commit 1c277f9c authored by Ulas Kirazci's avatar Ulas Kirazci

Fixed packed repeated serialization.

Remove buggy memoization. Memoization also is too fragile for the api
because the repeated field is public.

Change-Id: I538b8426d274b22df2eeea5935023abbe7df49fe
parent a91e2fc4
...@@ -46,6 +46,7 @@ import com.google.protobuf.nano.UnittestImportNano; ...@@ -46,6 +46,7 @@ import com.google.protobuf.nano.UnittestImportNano;
import junit.framework.TestCase; import junit.framework.TestCase;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
/** /**
...@@ -1955,6 +1956,24 @@ public class NanoTest extends TestCase { ...@@ -1955,6 +1956,24 @@ public class NanoTest extends TestCase {
assertEquals(TestAllTypesNano.BAR, msg.repeatedPackedNestedEnum[1]); assertEquals(TestAllTypesNano.BAR, msg.repeatedPackedNestedEnum[1]);
} }
public void testNanoRepeatedPackedSerializedSize() throws Exception {
TestAllTypesNano msg = new TestAllTypesNano();
msg.repeatedPackedInt32 = new int[] { 123, 789, 456 };
int msgSerializedSize = msg.getSerializedSize();
byte [] result = MessageNano.toByteArray(msg);
//System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
assertTrue(msgSerializedSize == 11);
assertEquals(result.length, msgSerializedSize);
TestAllTypesNano msg2 = new TestAllTypesNano();
msg2.repeatedPackedInt32 = new int[] { 123, 789, 456 };
byte [] result2 = new byte[msgSerializedSize];
MessageNano.toByteArray(msg2, result2, 0, msgSerializedSize);
// Check equal size and content.
assertEquals(msgSerializedSize, msg2.getSerializedSize());
assertTrue(Arrays.equals(result, result2));
}
public void testNanoRepeatedInt32ReMerge() throws Exception { public void testNanoRepeatedInt32ReMerge() throws Exception {
TestAllTypesNano msg = new TestAllTypesNano(); TestAllTypesNano msg = new TestAllTypesNano();
msg.repeatedInt32 = new int[] { 234 }; msg.repeatedInt32 = new int[] { 234 };
......
...@@ -401,10 +401,6 @@ void RepeatedPrimitiveFieldGenerator:: ...@@ -401,10 +401,6 @@ void RepeatedPrimitiveFieldGenerator::
GenerateMembers(io::Printer* printer) const { GenerateMembers(io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_,
"public $type$[] $name$ = $default$;\n"); "public $type$[] $name$ = $default$;\n");
if (descriptor_->options().packed()) {
printer->Print(variables_,
"private int $name$MemoizedSerializedSize;\n");
}
} }
void RepeatedPrimitiveFieldGenerator:: void RepeatedPrimitiveFieldGenerator::
...@@ -453,13 +449,34 @@ GenerateParsingCode(io::Printer* printer) const { ...@@ -453,13 +449,34 @@ GenerateParsingCode(io::Printer* printer) const {
} }
} }
void RepeatedPrimitiveFieldGenerator::
GenerateRepeatedDataSizeCode(io::Printer* printer) const {
// Creates a variable dataSize and puts the serialized size in
// there.
if (FixedSize(descriptor_->type()) == -1) {
printer->Print(variables_,
"int dataSize = 0;\n"
"for ($type$ element : this.$name$) {\n"
" dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .compute$capitalized_type$SizeNoTag(element);\n"
"}\n");
} else {
printer->Print(variables_,
"int dataSize = $fixed_size$ * this.$name$.length;\n");
}
}
void RepeatedPrimitiveFieldGenerator:: void RepeatedPrimitiveFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const { GenerateSerializationCode(io::Printer* printer) const {
if (descriptor_->options().packed()) { if (descriptor_->options().packed()) {
printer->Print(variables_, printer->Print(variables_,
"if (this.$name$.length > 0) {\n" "if (this.$name$.length > 0) {\n");
printer->Indent();
GenerateRepeatedDataSizeCode(printer);
printer->Outdent();
printer->Print(variables_,
" output.writeRawVarint32($tag$);\n" " output.writeRawVarint32($tag$);\n"
" output.writeRawVarint32($name$MemoizedSerializedSize);\n" " output.writeRawVarint32(dataSize);\n"
"}\n"); "}\n");
printer->Print(variables_, printer->Print(variables_,
"for ($type$ element : this.$name$) {\n" "for ($type$ element : this.$name$) {\n"
...@@ -479,27 +496,15 @@ GenerateSerializedSizeCode(io::Printer* printer) const { ...@@ -479,27 +496,15 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
"if (this.$name$.length > 0) {\n"); "if (this.$name$.length > 0) {\n");
printer->Indent(); printer->Indent();
if (FixedSize(descriptor_->type()) == -1) { GenerateRepeatedDataSizeCode(printer);
printer->Print(variables_,
"int dataSize = 0;\n"
"for ($type$ element : this.$name$) {\n"
" dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .compute$capitalized_type$SizeNoTag(element);\n"
"}\n");
} else {
printer->Print(variables_,
"int dataSize = $fixed_size$ * this.$name$.length;\n");
}
printer->Print( printer->Print(
"size += dataSize;\n"); "size += dataSize;\n");
if (descriptor_->options().packed()) { if (descriptor_->options().packed()) {
// cache the data size for packed fields.
printer->Print(variables_, printer->Print(variables_,
"size += $tag_size$;\n" "size += $tag_size$;\n"
"size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .computeRawVarint32Size(dataSize);\n" " .computeRawVarint32Size(dataSize);\n");
"$name$MemoizedSerializedSize = dataSize;\n");
} else { } else {
printer->Print(variables_, printer->Print(variables_,
"size += $tag_size$ * this.$name$.length;\n"); "size += $tag_size$ * this.$name$.length;\n");
...@@ -507,16 +512,8 @@ GenerateSerializedSizeCode(io::Printer* printer) const { ...@@ -507,16 +512,8 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Outdent(); printer->Outdent();
// set cached size to 0 for empty packed fields. printer->Print(
if (descriptor_->options().packed()) { "}\n");
printer->Print(variables_,
"} else {\n"
" $name$MemoizedSerializedSize = 0;\n"
"}\n");
} else {
printer->Print(
"}\n");
}
} }
string RepeatedPrimitiveFieldGenerator::GetBoxedType() const { string RepeatedPrimitiveFieldGenerator::GetBoxedType() const {
......
...@@ -78,6 +78,8 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator { ...@@ -78,6 +78,8 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
string GetBoxedType() const; string GetBoxedType() const;
private: private:
void GenerateRepeatedDataSizeCode(io::Printer* printer) const;
const FieldDescriptor* descriptor_; const FieldDescriptor* descriptor_;
map<string, string> variables_; map<string, string> variables_;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment