Commit 828b7e61 authored by Jon Skeet's avatar Jon Skeet

Use the fact that we know the tag size and bytes at codegen time to optimize.

parent fb1547b3
...@@ -139,13 +139,16 @@ namespace Google.ProtocolBuffers.Examples.AddressBook { ...@@ -139,13 +139,16 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
public void WriteTo(pb::CodedOutputStream output) { public void WriteTo(pb::CodedOutputStream output) {
if (Name.Length != 0) { if (Name.Length != 0) {
output.WriteString(1, Name); output.WriteRawTag(10);
output.WriteString(Name);
} }
if (Id != 0) { if (Id != 0) {
output.WriteInt32(2, Id); output.WriteRawTag(16);
output.WriteInt32(Id);
} }
if (Email.Length != 0) { if (Email.Length != 0) {
output.WriteString(3, Email); output.WriteRawTag(26);
output.WriteString(Email);
} }
if (phone_.Count > 0) { if (phone_.Count > 0) {
output.WriteMessageArray(4, phone_); output.WriteMessageArray(4, phone_);
...@@ -155,18 +158,19 @@ namespace Google.ProtocolBuffers.Examples.AddressBook { ...@@ -155,18 +158,19 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
public int CalculateSize() { public int CalculateSize() {
int size = 0; int size = 0;
if (Name.Length != 0) { if (Name.Length != 0) {
size += pb::CodedOutputStream.ComputeStringSize(1, Name); size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
} }
if (Id != 0) { if (Id != 0) {
size += pb::CodedOutputStream.ComputeInt32Size(2, Id); size += 1 + pb::CodedOutputStream.ComputeInt32Size(Id);
} }
if (Email.Length != 0) { if (Email.Length != 0) {
size += pb::CodedOutputStream.ComputeStringSize(3, Email); size += 1 + pb::CodedOutputStream.ComputeStringSize(Email);
} }
if (phone_.Count > 0) { if (phone_.Count > 0) {
foreach (global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber element in phone_) { foreach (global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber element in phone_) {
size += pb::CodedOutputStream.ComputeMessageSize(4, element); size += pb::CodedOutputStream.ComputeMessageSize(element);
} }
size += 1 * phone_.Count;
} }
return size; return size;
} }
...@@ -286,20 +290,22 @@ namespace Google.ProtocolBuffers.Examples.AddressBook { ...@@ -286,20 +290,22 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
public void WriteTo(pb::CodedOutputStream output) { public void WriteTo(pb::CodedOutputStream output) {
if (Number.Length != 0) { if (Number.Length != 0) {
output.WriteString(1, Number); output.WriteRawTag(10);
output.WriteString(Number);
} }
if (Type != global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneType.HOME) { if (Type != global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneType.HOME) {
output.WriteEnum(2, (int) Type); output.WriteRawTag(16);
output.WriteEnum((int) Type);
} }
} }
public int CalculateSize() { public int CalculateSize() {
int size = 0; int size = 0;
if (Number.Length != 0) { if (Number.Length != 0) {
size += pb::CodedOutputStream.ComputeStringSize(1, Number); size += 1 + pb::CodedOutputStream.ComputeStringSize(Number);
} }
if (Type != global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneType.HOME) { if (Type != global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneType.HOME) {
size += pb::CodedOutputStream.ComputeEnumSize(2, (int) Type); size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type);
} }
return size; return size;
} }
...@@ -401,8 +407,9 @@ namespace Google.ProtocolBuffers.Examples.AddressBook { ...@@ -401,8 +407,9 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
int size = 0; int size = 0;
if (person_.Count > 0) { if (person_.Count > 0) {
foreach (global::Google.ProtocolBuffers.Examples.AddressBook.Person element in person_) { foreach (global::Google.ProtocolBuffers.Examples.AddressBook.Person element in person_) {
size += pb::CodedOutputStream.ComputeMessageSize(1, element); size += pb::CodedOutputStream.ComputeMessageSize(element);
} }
size += 1 * person_.Count;
} }
return size; return size;
} }
......
...@@ -38,6 +38,8 @@ using System; ...@@ -38,6 +38,8 @@ using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using Google.Protobuf;
using Google.Protobuf.Descriptors;
using Google.ProtocolBuffers.Descriptors; using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.ProtoMunge namespace Google.ProtocolBuffers.ProtoMunge
......
...@@ -479,7 +479,8 @@ namespace Google.Protobuf ...@@ -479,7 +479,8 @@ namespace Google.Protobuf
int msgSize = 1 + 1 + arraySize; int msgSize = 1 + 1 + arraySize;
byte[] bytes = new byte[msgSize]; byte[] bytes = new byte[msgSize];
CodedOutputStream output = CodedOutputStream.CreateInstance(bytes); CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
output.WritePackedInt32Array(8, new RepeatedField<int> { 0, -1, -2, -3, -4, -5 }); output.WriteTag(8, WireFormat.WireType.LengthDelimited);
output.WritePackedInt32Array(new RepeatedField<int> { 0, -1, -2, -3, -4, -5 });
Assert.AreEqual(0, output.SpaceLeft); Assert.AreEqual(0, output.SpaceLeft);
...@@ -527,8 +528,10 @@ namespace Google.Protobuf ...@@ -527,8 +528,10 @@ namespace Google.Protobuf
using (var ms = new MemoryStream()) using (var ms = new MemoryStream())
{ {
CodedOutputStream output = CodedOutputStream.CreateInstance(ms); CodedOutputStream output = CodedOutputStream.CreateInstance(ms);
output.WriteBytes(1, ByteString.CopyFrom(new byte[100])); output.WriteTag(1, WireFormat.WireType.LengthDelimited);
output.WriteBytes(2, ByteString.CopyFrom(new byte[100])); output.WriteBytes(ByteString.CopyFrom(new byte[100]));
output.WriteTag(2, WireFormat.WireType.LengthDelimited);
output.WriteBytes(ByteString.CopyFrom(new byte[100]));
output.Flush(); output.Flush();
ms.Position = 0; ms.Position = 0;
......
...@@ -295,12 +295,12 @@ namespace Google.Protobuf ...@@ -295,12 +295,12 @@ namespace Google.Protobuf
[Test] [Test]
public void TestNegativeEnumNoTag() public void TestNegativeEnumNoTag()
{ {
Assert.AreEqual(10, CodedOutputStream.ComputeInt32SizeNoTag(-2)); Assert.AreEqual(10, CodedOutputStream.ComputeInt32Size(-2));
Assert.AreEqual(10, CodedOutputStream.ComputeEnumSizeNoTag((int) TestNegEnum.Value)); Assert.AreEqual(10, CodedOutputStream.ComputeEnumSize((int) TestNegEnum.Value));
byte[] bytes = new byte[10]; byte[] bytes = new byte[10];
CodedOutputStream output = CodedOutputStream.CreateInstance(bytes); CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
output.WriteEnumNoTag((int) TestNegEnum.Value); output.WriteEnum((int) TestNegEnum.Value);
Assert.AreEqual(0, output.SpaceLeft); Assert.AreEqual(0, output.SpaceLeft);
Assert.AreEqual("FE-FF-FF-FF-FF-FF-FF-FF-FF-01", BitConverter.ToString(bytes)); Assert.AreEqual("FE-FF-FF-FF-FF-FF-FF-FF-FF-01", BitConverter.ToString(bytes));
...@@ -308,21 +308,6 @@ namespace Google.Protobuf ...@@ -308,21 +308,6 @@ namespace Google.Protobuf
enum TestNegEnum { None = 0, Value = -2 } enum TestNegEnum { None = 0, Value = -2 }
[Test]
public void TestNegativeEnumWithTag()
{
Assert.AreEqual(11, CodedOutputStream.ComputeInt32Size(8, -2));
Assert.AreEqual(11, CodedOutputStream.ComputeEnumSize(8, (int) TestNegEnum.Value));
byte[] bytes = new byte[11];
CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
output.WriteEnum(8, (int) TestNegEnum.Value);
Assert.AreEqual(0, output.SpaceLeft);
//fyi, 0x40 == 0x08 << 3 + 0, field num + wire format shift
Assert.AreEqual("40-FE-FF-FF-FF-FF-FF-FF-FF-FF-01", BitConverter.ToString(bytes));
}
[Test] [Test]
public void TestNegativeEnumArrayPacked() public void TestNegativeEnumArrayPacked()
{ {
...@@ -330,7 +315,8 @@ namespace Google.Protobuf ...@@ -330,7 +315,8 @@ namespace Google.Protobuf
int msgSize = 1 + 1 + arraySize; int msgSize = 1 + 1 + arraySize;
byte[] bytes = new byte[msgSize]; byte[] bytes = new byte[msgSize];
CodedOutputStream output = CodedOutputStream.CreateInstance(bytes); CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
output.WritePackedEnumArray(8, new RepeatedField<TestNegEnum> { output.WriteTag(8, WireFormat.WireType.LengthDelimited);
output.WritePackedEnumArray(new RepeatedField<TestNegEnum> {
0, (TestNegEnum) (-1), TestNegEnum.Value, (TestNegEnum) (-3), (TestNegEnum) (-4), (TestNegEnum) (-5) }); 0, (TestNegEnum) (-1), TestNegEnum.Value, (TestNegEnum) (-3), (TestNegEnum) (-4), (TestNegEnum) (-5) });
Assert.AreEqual(0, output.SpaceLeft); Assert.AreEqual(0, output.SpaceLeft);
...@@ -384,17 +370,17 @@ namespace Google.Protobuf ...@@ -384,17 +370,17 @@ namespace Google.Protobuf
// Field 11: numeric value: 500 // Field 11: numeric value: 500
cout.WriteTag(11, WireFormat.WireType.Varint); cout.WriteTag(11, WireFormat.WireType.Varint);
Assert.AreEqual(1, cout.Position); Assert.AreEqual(1, cout.Position);
cout.WriteInt32NoTag(500); cout.WriteInt32(500);
Assert.AreEqual(3, cout.Position); Assert.AreEqual(3, cout.Position);
//Field 12: length delimited 120 bytes //Field 12: length delimited 120 bytes
cout.WriteTag(12, WireFormat.WireType.LengthDelimited); cout.WriteTag(12, WireFormat.WireType.LengthDelimited);
Assert.AreEqual(4, cout.Position); Assert.AreEqual(4, cout.Position);
cout.WriteBytesNoTag(ByteString.CopyFrom(content)); cout.WriteBytes(ByteString.CopyFrom(content));
Assert.AreEqual(115, cout.Position); Assert.AreEqual(115, cout.Position);
// Field 13: fixed numeric value: 501 // Field 13: fixed numeric value: 501
cout.WriteTag(13, WireFormat.WireType.Fixed32); cout.WriteTag(13, WireFormat.WireType.Fixed32);
Assert.AreEqual(116, cout.Position); Assert.AreEqual(116, cout.Position);
cout.WriteSFixed32NoTag(501); cout.WriteSFixed32(501);
Assert.AreEqual(120, cout.Position); Assert.AreEqual(120, cout.Position);
cout.Flush(); cout.Flush();
} }
...@@ -405,17 +391,17 @@ namespace Google.Protobuf ...@@ -405,17 +391,17 @@ namespace Google.Protobuf
// Field 1: numeric value: 500 // Field 1: numeric value: 500
cout.WriteTag(1, WireFormat.WireType.Varint); cout.WriteTag(1, WireFormat.WireType.Varint);
Assert.AreEqual(1, cout.Position); Assert.AreEqual(1, cout.Position);
cout.WriteInt32NoTag(500); cout.WriteInt32(500);
Assert.AreEqual(3, cout.Position); Assert.AreEqual(3, cout.Position);
//Field 2: length delimited 120 bytes //Field 2: length delimited 120 bytes
cout.WriteTag(2, WireFormat.WireType.LengthDelimited); cout.WriteTag(2, WireFormat.WireType.LengthDelimited);
Assert.AreEqual(4, cout.Position); Assert.AreEqual(4, cout.Position);
cout.WriteBytesNoTag(ByteString.CopyFrom(child)); cout.WriteBytes(ByteString.CopyFrom(child));
Assert.AreEqual(125, cout.Position); Assert.AreEqual(125, cout.Position);
// Field 3: fixed numeric value: 500 // Field 3: fixed numeric value: 500
cout.WriteTag(3, WireFormat.WireType.Fixed32); cout.WriteTag(3, WireFormat.WireType.Fixed32);
Assert.AreEqual(126, cout.Position); Assert.AreEqual(126, cout.Position);
cout.WriteSFixed32NoTag(501); cout.WriteSFixed32(501);
Assert.AreEqual(130, cout.Position); Assert.AreEqual(130, cout.Position);
cout.Flush(); cout.Flush();
} }
......
...@@ -109,14 +109,15 @@ namespace Google.Protobuf.TestProtos { ...@@ -109,14 +109,15 @@ namespace Google.Protobuf.TestProtos {
public void WriteTo(pb::CodedOutputStream output) { public void WriteTo(pb::CodedOutputStream output) {
if (D != 0) { if (D != 0) {
output.WriteInt32(1, D); output.WriteRawTag(8);
output.WriteInt32(D);
} }
} }
public int CalculateSize() { public int CalculateSize() {
int size = 0; int size = 0;
if (D != 0) { if (D != 0) {
size += pb::CodedOutputStream.ComputeInt32Size(1, D); size += 1 + pb::CodedOutputStream.ComputeInt32Size(D);
} }
return size; return size;
} }
......
...@@ -94,14 +94,15 @@ namespace Google.Protobuf.TestProtos { ...@@ -94,14 +94,15 @@ namespace Google.Protobuf.TestProtos {
public void WriteTo(pb::CodedOutputStream output) { public void WriteTo(pb::CodedOutputStream output) {
if (E != 0) { if (E != 0) {
output.WriteInt32(1, E); output.WriteRawTag(8);
output.WriteInt32(E);
} }
} }
public int CalculateSize() { public int CalculateSize() {
int size = 0; int size = 0;
if (E != 0) { if (E != 0) {
size += pb::CodedOutputStream.ComputeInt32Size(1, E); size += 1 + pb::CodedOutputStream.ComputeInt32Size(E);
} }
return size; return size;
} }
......
...@@ -155,25 +155,27 @@ namespace UnitTest.Issues.TestProtos { ...@@ -155,25 +155,27 @@ namespace UnitTest.Issues.TestProtos {
public void WriteTo(pb::CodedOutputStream output) { public void WriteTo(pb::CodedOutputStream output) {
if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO) { if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO) {
output.WriteEnum(1, (int) Value); output.WriteRawTag(8);
output.WriteEnum((int) Value);
} }
if (values_.Count > 0) { if (values_.Count > 0) {
output.WriteEnumArray(2, values_); output.WriteEnumArray(2, values_);
} }
if (packedValues_.Count > 0) { if (packedValues_.Count > 0) {
output.WritePackedEnumArray(3, packedValues_); output.WriteRawTag(26);
output.WritePackedEnumArray(packedValues_);
} }
} }
public int CalculateSize() { public int CalculateSize() {
int size = 0; int size = 0;
if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO) { if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO) {
size += pb::CodedOutputStream.ComputeEnumSize(1, (int) Value); size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Value);
} }
if (values_.Count > 0) { if (values_.Count > 0) {
int dataSize = 0; int dataSize = 0;
foreach (global::UnitTest.Issues.TestProtos.NegativeEnum element in values_) { foreach (global::UnitTest.Issues.TestProtos.NegativeEnum element in values_) {
dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element); dataSize += pb::CodedOutputStream.ComputeEnumSize((int) element);
} }
size += dataSize; size += dataSize;
size += 1 * values_.Count; size += 1 * values_.Count;
...@@ -181,11 +183,10 @@ namespace UnitTest.Issues.TestProtos { ...@@ -181,11 +183,10 @@ namespace UnitTest.Issues.TestProtos {
if (packedValues_.Count > 0) { if (packedValues_.Count > 0) {
int dataSize = 0; int dataSize = 0;
foreach (global::UnitTest.Issues.TestProtos.NegativeEnum element in packedValues_) { foreach (global::UnitTest.Issues.TestProtos.NegativeEnum element in packedValues_) {
dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element); dataSize += pb::CodedOutputStream.ComputeEnumSize((int) element);
} }
size += dataSize; size += dataSize;
size += 1; size += 1 + pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);
size += pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);
} }
return size; return size;
} }
...@@ -305,7 +306,7 @@ namespace UnitTest.Issues.TestProtos { ...@@ -305,7 +306,7 @@ namespace UnitTest.Issues.TestProtos {
public static pb::MessageParser<DeprecatedFieldsMessage> Parser { get { return _parser; } } public static pb::MessageParser<DeprecatedFieldsMessage> Parser { get { return _parser; } }
private static readonly string[] _fieldNames = new string[] { "EnumArray", "EnumValue", "MessageArray", "MessageValue", "PrimitiveArray", "PrimitiveValue" }; private static readonly string[] _fieldNames = new string[] { "EnumArray", "EnumValue", "MessageArray", "MessageValue", "PrimitiveArray", "PrimitiveValue" };
private static readonly uint[] _fieldTags = new uint[] { 48, 40, 34, 26, 16, 8 }; private static readonly uint[] _fieldTags = new uint[] { 50, 40, 34, 26, 18, 8 };
public static pbd::MessageDescriptor Descriptor { public static pbd::MessageDescriptor Descriptor {
get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_DeprecatedFieldsMessage__Descriptor; } get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_DeprecatedFieldsMessage__Descriptor; }
} }
...@@ -397,57 +398,62 @@ namespace UnitTest.Issues.TestProtos { ...@@ -397,57 +398,62 @@ namespace UnitTest.Issues.TestProtos {
public void WriteTo(pb::CodedOutputStream output) { public void WriteTo(pb::CodedOutputStream output) {
if (PrimitiveValue != 0) { if (PrimitiveValue != 0) {
output.WriteInt32(1, PrimitiveValue); output.WriteRawTag(8);
output.WriteInt32(PrimitiveValue);
} }
if (primitiveArray_.Count > 0) { if (primitiveArray_.Count > 0) {
output.WritePackedInt32Array(2, primitiveArray_); output.WriteRawTag(18);
output.WritePackedInt32Array(primitiveArray_);
} }
if (messageValue_ != null) { if (messageValue_ != null) {
output.WriteMessage(3, MessageValue); output.WriteRawTag(26);
output.WriteMessage(MessageValue);
} }
if (messageArray_.Count > 0) { if (messageArray_.Count > 0) {
output.WriteMessageArray(4, messageArray_); output.WriteMessageArray(4, messageArray_);
} }
if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO) { if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO) {
output.WriteEnum(5, (int) EnumValue); output.WriteRawTag(40);
output.WriteEnum((int) EnumValue);
} }
if (enumArray_.Count > 0) { if (enumArray_.Count > 0) {
output.WritePackedEnumArray(6, enumArray_); output.WriteRawTag(50);
output.WritePackedEnumArray(enumArray_);
} }
} }
public int CalculateSize() { public int CalculateSize() {
int size = 0; int size = 0;
if (PrimitiveValue != 0) { if (PrimitiveValue != 0) {
size += pb::CodedOutputStream.ComputeInt32Size(1, PrimitiveValue); size += 1 + pb::CodedOutputStream.ComputeInt32Size(PrimitiveValue);
} }
if (primitiveArray_.Count > 0) { if (primitiveArray_.Count > 0) {
int dataSize = 0; int dataSize = 0;
foreach (int element in primitiveArray_) { foreach (int element in primitiveArray_) {
dataSize += pb::CodedOutputStream.ComputeInt32SizeNoTag(element); dataSize += pb::CodedOutputStream.ComputeInt32Size(element);
} }
size += dataSize; size += dataSize;
size += 1 + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize); size += 1 + pb::CodedOutputStream.ComputeInt32Size(dataSize);
} }
if (messageValue_ != null) { if (messageValue_ != null) {
size += pb::CodedOutputStream.ComputeMessageSize(3, MessageValue); size += 1 + pb::CodedOutputStream.ComputeMessageSize(MessageValue);
} }
if (messageArray_.Count > 0) { if (messageArray_.Count > 0) {
foreach (global::UnitTest.Issues.TestProtos.DeprecatedChild element in messageArray_) { foreach (global::UnitTest.Issues.TestProtos.DeprecatedChild element in messageArray_) {
size += pb::CodedOutputStream.ComputeMessageSize(4, element); size += pb::CodedOutputStream.ComputeMessageSize(element);
} }
size += 1 * messageArray_.Count;
} }
if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO) { if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO) {
size += pb::CodedOutputStream.ComputeEnumSize(5, (int) EnumValue); size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) EnumValue);
} }
if (enumArray_.Count > 0) { if (enumArray_.Count > 0) {
int dataSize = 0; int dataSize = 0;
foreach (global::UnitTest.Issues.TestProtos.DeprecatedEnum element in enumArray_) { foreach (global::UnitTest.Issues.TestProtos.DeprecatedEnum element in enumArray_) {
dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element); dataSize += pb::CodedOutputStream.ComputeEnumSize((int) element);
} }
size += dataSize; size += dataSize;
size += 1; size += 1 + pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);
size += pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);
} }
return size; return size;
} }
...@@ -568,14 +574,15 @@ namespace UnitTest.Issues.TestProtos { ...@@ -568,14 +574,15 @@ namespace UnitTest.Issues.TestProtos {
public void WriteTo(pb::CodedOutputStream output) { public void WriteTo(pb::CodedOutputStream output) {
if (Item != 0) { if (Item != 0) {
output.WriteInt32(1, Item); output.WriteRawTag(8);
output.WriteInt32(Item);
} }
} }
public int CalculateSize() { public int CalculateSize() {
int size = 0; int size = 0;
if (Item != 0) { if (Item != 0) {
size += pb::CodedOutputStream.ComputeInt32Size(1, Item); size += 1 + pb::CodedOutputStream.ComputeInt32Size(Item);
} }
return size; return size;
} }
......
...@@ -61,7 +61,8 @@ void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { ...@@ -61,7 +61,8 @@ void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) {
void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
printer->Print(variables_, printer->Print(variables_,
"if ($has_property_check$) {\n" "if ($has_property_check$) {\n"
" output.WriteEnum($number$, (int) $property_name$);\n" " output.WriteRawTag($tag_bytes$);\n"
" output.WriteEnum((int) $property_name$);\n"
"}\n"); "}\n");
} }
...@@ -69,7 +70,7 @@ void EnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { ...@@ -69,7 +70,7 @@ void EnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print( printer->Print(
variables_, variables_,
"if ($has_property_check$) {\n" "if ($has_property_check$) {\n"
" size += pb::CodedOutputStream.ComputeEnumSize($number$, (int) $property_name$);\n" " size += $tag_size$ + pb::CodedOutputStream.ComputeEnumSize((int) $property_name$);\n"
"}\n"); "}\n");
} }
...@@ -93,7 +94,8 @@ void EnumOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) { ...@@ -93,7 +94,8 @@ void EnumOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
printer->Print( printer->Print(
variables_, variables_,
"if ($has_property_check$) {\n" "if ($has_property_check$) {\n"
" output.WriteEnum($number$, (int) $property_name$);\n" " output.WriteRawTag($tag_bytes$);\n"
" output.WriteEnum((int) $property_name$);\n"
"}\n"); "}\n");
} }
...@@ -101,7 +103,7 @@ void EnumOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { ...@@ -101,7 +103,7 @@ void EnumOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print( printer->Print(
variables_, variables_,
"if ($has_property_check$) {\n" "if ($has_property_check$) {\n"
" size += pb::CodedOutputStream.ComputeEnumSize($number$, (int) $property_name$);\n" " size += $tag_size$ + pb::CodedOutputStream.ComputeEnumSize((int) $property_name$);\n"
"}\n"); "}\n");
} }
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <google/protobuf/compiler/plugin.h> #include <google/protobuf/compiler/plugin.h>
#include <google/protobuf/descriptor.h> #include <google/protobuf/descriptor.h>
#include <google/protobuf/descriptor.pb.h> #include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/printer.h> #include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h> #include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/stubs/strutil.h> #include <google/protobuf/stubs/strutil.h>
...@@ -55,8 +56,18 @@ void FieldGeneratorBase::SetCommonFieldVariables( ...@@ -55,8 +56,18 @@ void FieldGeneratorBase::SetCommonFieldVariables(
// Note: this will be valid even though the tag emitted for packed and unpacked versions of // Note: this will be valid even though the tag emitted for packed and unpacked versions of
// repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which // repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which
// never effects the tag size. // never effects the tag size.
int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); int tag_size = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type());
(*variables)["tag_size"] = SimpleItoa(tagSize); uint tag = internal::WireFormat::MakeTag(descriptor_);
uint8 tag_array[5];
io::CodedOutputStream::WriteTagToArray(tag, tag_array);
string tag_bytes = SimpleItoa(tag_array[0]);
for (int i = 1; i < tag_size; i++) {
tag_bytes += ", " + SimpleItoa(tag_array[i]);
}
(*variables)["tag_size"] = SimpleItoa(tag_size);
(*variables)["tag_bytes"] = tag_bytes;
(*variables)["property_name"] = property_name(); (*variables)["property_name"] = property_name();
(*variables)["type_name"] = type_name(); (*variables)["type_name"] = type_name();
(*variables)["name"] = name(); (*variables)["name"] = name();
......
...@@ -92,11 +92,11 @@ void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) { ...@@ -92,11 +92,11 @@ void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) {
} }
void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) { void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
// TODO(jonskeet): Why are we using array access instead of a literal here?
printer->Print( printer->Print(
variables_, variables_,
"if ($has_property_check$) {\n" "if ($has_property_check$) {\n"
" output.WriteMessage($number$, $property_name$);\n" " output.WriteRawTag($tag_bytes$);\n"
" output.WriteMessage($property_name$);\n"
"}\n"); "}\n");
} }
...@@ -104,7 +104,7 @@ void MessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { ...@@ -104,7 +104,7 @@ void MessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print( printer->Print(
variables_, variables_,
"if ($has_property_check$) {\n" "if ($has_property_check$) {\n"
" size += pb::CodedOutputStream.ComputeMessageSize($number$, $property_name$);\n" " size += $tag_size$ + pb::CodedOutputStream.ComputeMessageSize($property_name$);\n"
"}\n"); "}\n");
} }
......
...@@ -105,16 +105,29 @@ void PrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) { ...@@ -105,16 +105,29 @@ void PrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
printer->Print( printer->Print(
variables_, variables_,
"if ($has_property_check$) {\n" "if ($has_property_check$) {\n"
" output.Write$capitalized_type_name$($number$, $property_name$);\n" " output.WriteRawTag($tag_bytes$);\n"
" output.Write$capitalized_type_name$($property_name$);\n"
"}\n"); "}\n");
} }
void PrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { void PrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print( printer->Print(
variables_, variables_,
"if ($has_property_check$) {\n" "if ($has_property_check$) {\n");
" size += pb::CodedOutputStream.Compute$capitalized_type_name$Size($number$, $property_name$);\n" printer->Indent();
"}\n"); int fixedSize = GetFixedSize(descriptor_->type());
if (fixedSize == -1) {
printer->Print(
variables_,
"size += $tag_size$ + pb::CodedOutputStream.Compute$capitalized_type_name$Size($property_name$);\n");
} else {
printer->Print(
"size += $tag_size$ + $fixed_size$;\n",
"fixed_size", SimpleItoa(fixedSize),
"tag_size", variables_["tag_size"]);
}
printer->Outdent();
printer->Print("}\n");
} }
void PrimitiveFieldGenerator::WriteHash(io::Printer* printer) { void PrimitiveFieldGenerator::WriteHash(io::Printer* printer) {
...@@ -173,7 +186,7 @@ void PrimitiveOneofFieldGenerator::WriteToString(io::Printer* printer) { ...@@ -173,7 +186,7 @@ void PrimitiveOneofFieldGenerator::WriteToString(io::Printer* printer) {
void PrimitiveOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { void PrimitiveOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
printer->Print( printer->Print(
variables_, variables_,
"$property_name$ = input.Read$capitalized_type_name$()\n;"); "$property_name$ = input.Read$capitalized_type_name$();\n");
} }
} // namespace csharp } // namespace csharp
......
...@@ -82,9 +82,20 @@ void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { ...@@ -82,9 +82,20 @@ void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer) {
void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
printer->Print( printer->Print(
variables_, variables_,
"if ($name$_.Count > 0) {\n" "if ($name$_.Count > 0) {\n");
" output.Write$packed$EnumArray($number$, $name$_);\n" printer->Indent();
"}\n"); if (descriptor_->is_packed()) {
printer->Print(
variables_,
"output.WriteRawTag($tag_bytes$);\n"
"output.WritePackedEnumArray($name$_);\n");
} else {
printer->Print(
variables_,
"output.Write$capitalized_type_name$Array($number$, $name$_);\n");
}
printer->Outdent();
printer->Print("}\n");
} }
void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
...@@ -97,14 +108,13 @@ void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer ...@@ -97,14 +108,13 @@ void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer
printer->Print( printer->Print(
variables_, variables_,
"foreach ($type_name$ element in $name$_) {\n" "foreach ($type_name$ element in $name$_) {\n"
" dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);\n" " dataSize += pb::CodedOutputStream.ComputeEnumSize((int) element);\n"
"}\n" "}\n"
"size += dataSize;\n"); "size += dataSize;\n");
int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type());
if (descriptor_->is_packed()) { if (descriptor_->is_packed()) {
printer->Print( printer->Print(
"size += $tag_size$;\n" "size += $tag_size$ + pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);\n",
"size += pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);\n",
"tag_size", SimpleItoa(tagSize)); "tag_size", SimpleItoa(tagSize));
} else { } else {
printer->Print( printer->Print(
......
...@@ -79,8 +79,8 @@ void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer) { ...@@ -79,8 +79,8 @@ void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer) {
} }
void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) { void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
// TODO(jonskeet): Originally, this checked for Count > 0 first. // TODO(jonskeet): Bake the foreach loop into the generated code? We lose the
// The Write* call should make that cheap though - no need to generate it every time. // advantage of knowing the tag bytes this way :(
printer->Print( printer->Print(
variables_, variables_,
"if ($name$_.Count > 0) {\n" "if ($name$_.Count > 0) {\n"
...@@ -89,13 +89,13 @@ void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* print ...@@ -89,13 +89,13 @@ void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* print
} }
void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
// TODO(jonskeet): Put this into CodedOutputStream.
printer->Print( printer->Print(
variables_, variables_,
"if ($name$_.Count > 0) {\n" "if ($name$_.Count > 0) {\n"
" foreach ($type_name$ element in $name$_) {\n" " foreach ($type_name$ element in $name$_) {\n"
" size += pb::CodedOutputStream.ComputeMessageSize($number$, element);\n" " size += pb::CodedOutputStream.ComputeMessageSize(element);\n"
" }\n" " }\n"
" size += $tag_size$ * $name$_.Count;\n"
"}\n"); "}\n");
} }
......
...@@ -82,9 +82,20 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode( ...@@ -82,9 +82,20 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode(
io::Printer* printer) { io::Printer* printer) {
printer->Print( printer->Print(
variables_, variables_,
"if ($name$_.Count > 0) {\n" "if ($name$_.Count > 0) {\n");
" output.Write$packed$$capitalized_type_name$Array($number$, $name$_);\n" printer->Indent();
"}\n"); if (descriptor_->is_packed()) {
printer->Print(
variables_,
"output.WriteRawTag($tag_bytes$);\n"
"output.WritePacked$capitalized_type_name$Array($name$_);\n");
} else {
printer->Print(
variables_,
"output.Write$capitalized_type_name$Array($number$, $name$_);\n");
}
printer->Outdent();
printer->Print("}\n");
} }
void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode( void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode(
...@@ -100,7 +111,7 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode( ...@@ -100,7 +111,7 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode(
printer->Print( printer->Print(
variables_, variables_,
"foreach ($type_name$ element in $name$_) {\n" "foreach ($type_name$ element in $name$_) {\n"
" dataSize += pb::CodedOutputStream.Compute$capitalized_type_name$SizeNoTag(element);\n" " dataSize += pb::CodedOutputStream.Compute$capitalized_type_name$Size(element);\n"
"}\n"); "}\n");
} else { } else {
printer->Print( printer->Print(
...@@ -111,7 +122,7 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode( ...@@ -111,7 +122,7 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode(
int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type());
if (descriptor_->is_packed()) { if (descriptor_->is_packed()) {
printer->Print( printer->Print(
"size += $tag_size$ + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize);\n", "size += $tag_size$ + pb::CodedOutputStream.ComputeInt32Size(dataSize);\n",
"tag_size", SimpleItoa(tagSize)); "tag_size", SimpleItoa(tagSize));
} else { } else {
printer->Print( printer->Print(
......
...@@ -290,7 +290,7 @@ class LIBPROTOBUF_EXPORT UnknownFieldSetFieldSkipper : public FieldSkipper { ...@@ -290,7 +290,7 @@ class LIBPROTOBUF_EXPORT UnknownFieldSetFieldSkipper : public FieldSkipper {
inline WireFormatLite::WireType WireFormat::WireTypeForField( inline WireFormatLite::WireType WireFormat::WireTypeForField(
const FieldDescriptor* field) { const FieldDescriptor* field) {
if (field->options().packed()) { if (field->is_packed()) {
return WireFormatLite::WIRETYPE_LENGTH_DELIMITED; return WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
} else { } else {
return WireTypeForFieldType(field->type()); return WireTypeForFieldType(field->type());
......
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