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

pull/515/head
Jon Skeet 10 years ago
parent fb1547b388
commit 828b7e61d0
  1. 31
      csharp/src/AddressBook/Addressbook.cs
  2. 2
      csharp/src/ProtoMunge/Program.cs
  3. 9
      csharp/src/ProtocolBuffers.Test/CodedInputStreamTest.cs
  4. 36
      csharp/src/ProtocolBuffers.Test/CodedOutputStreamTest.cs
  5. 5
      csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs
  6. 5
      csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportPublicProto3.cs
  7. 55
      csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs
  8. 613
      csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs
  9. 220
      csharp/src/ProtocolBuffers/CodedOutputStream.ComputeSize.cs
  10. 617
      csharp/src/ProtocolBuffers/CodedOutputStream.cs
  11. 458
      csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs
  12. 10
      src/google/protobuf/compiler/csharp/csharp_enum_field.cc
  13. 15
      src/google/protobuf/compiler/csharp/csharp_field_base.cc
  14. 6
      src/google/protobuf/compiler/csharp/csharp_message_field.cc
  15. 23
      src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
  16. 22
      src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
  17. 8
      src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
  18. 21
      src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
  19. 2
      src/google/protobuf/wire_format.h

@ -139,13 +139,16 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
public void WriteTo(pb::CodedOutputStream output) {
if (Name.Length != 0) {
output.WriteString(1, Name);
output.WriteRawTag(10);
output.WriteString(Name);
}
if (Id != 0) {
output.WriteInt32(2, Id);
output.WriteRawTag(16);
output.WriteInt32(Id);
}
if (Email.Length != 0) {
output.WriteString(3, Email);
output.WriteRawTag(26);
output.WriteString(Email);
}
if (phone_.Count > 0) {
output.WriteMessageArray(4, phone_);
@ -155,18 +158,19 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
public int CalculateSize() {
int size = 0;
if (Name.Length != 0) {
size += pb::CodedOutputStream.ComputeStringSize(1, Name);
size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
}
if (Id != 0) {
size += pb::CodedOutputStream.ComputeInt32Size(2, Id);
size += 1 + pb::CodedOutputStream.ComputeInt32Size(Id);
}
if (Email.Length != 0) {
size += pb::CodedOutputStream.ComputeStringSize(3, Email);
size += 1 + pb::CodedOutputStream.ComputeStringSize(Email);
}
if (phone_.Count > 0) {
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;
}
@ -286,20 +290,22 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
public void WriteTo(pb::CodedOutputStream output) {
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) {
output.WriteEnum(2, (int) Type);
output.WriteRawTag(16);
output.WriteEnum((int) Type);
}
}
public int CalculateSize() {
int size = 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) {
size += pb::CodedOutputStream.ComputeEnumSize(2, (int) Type);
size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type);
}
return size;
}
@ -401,8 +407,9 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
int size = 0;
if (person_.Count > 0) {
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;
}

@ -38,6 +38,8 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using Google.Protobuf;
using Google.Protobuf.Descriptors;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.ProtoMunge

@ -479,7 +479,8 @@ namespace Google.Protobuf
int msgSize = 1 + 1 + arraySize;
byte[] bytes = new byte[msgSize];
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);
@ -527,8 +528,10 @@ namespace Google.Protobuf
using (var ms = new MemoryStream())
{
CodedOutputStream output = CodedOutputStream.CreateInstance(ms);
output.WriteBytes(1, ByteString.CopyFrom(new byte[100]));
output.WriteBytes(2, ByteString.CopyFrom(new byte[100]));
output.WriteTag(1, WireFormat.WireType.LengthDelimited);
output.WriteBytes(ByteString.CopyFrom(new byte[100]));
output.WriteTag(2, WireFormat.WireType.LengthDelimited);
output.WriteBytes(ByteString.CopyFrom(new byte[100]));
output.Flush();
ms.Position = 0;

@ -295,12 +295,12 @@ namespace Google.Protobuf
[Test]
public void TestNegativeEnumNoTag()
{
Assert.AreEqual(10, CodedOutputStream.ComputeInt32SizeNoTag(-2));
Assert.AreEqual(10, CodedOutputStream.ComputeEnumSizeNoTag((int) TestNegEnum.Value));
Assert.AreEqual(10, CodedOutputStream.ComputeInt32Size(-2));
Assert.AreEqual(10, CodedOutputStream.ComputeEnumSize((int) TestNegEnum.Value));
byte[] bytes = new byte[10];
CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
output.WriteEnumNoTag((int) TestNegEnum.Value);
output.WriteEnum((int) TestNegEnum.Value);
Assert.AreEqual(0, output.SpaceLeft);
Assert.AreEqual("FE-FF-FF-FF-FF-FF-FF-FF-FF-01", BitConverter.ToString(bytes));
@ -308,21 +308,6 @@ namespace Google.Protobuf
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]
public void TestNegativeEnumArrayPacked()
{
@ -330,7 +315,8 @@ namespace Google.Protobuf
int msgSize = 1 + 1 + arraySize;
byte[] bytes = new byte[msgSize];
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) });
Assert.AreEqual(0, output.SpaceLeft);
@ -384,17 +370,17 @@ namespace Google.Protobuf
// Field 11: numeric value: 500
cout.WriteTag(11, WireFormat.WireType.Varint);
Assert.AreEqual(1, cout.Position);
cout.WriteInt32NoTag(500);
cout.WriteInt32(500);
Assert.AreEqual(3, cout.Position);
//Field 12: length delimited 120 bytes
cout.WriteTag(12, WireFormat.WireType.LengthDelimited);
Assert.AreEqual(4, cout.Position);
cout.WriteBytesNoTag(ByteString.CopyFrom(content));
cout.WriteBytes(ByteString.CopyFrom(content));
Assert.AreEqual(115, cout.Position);
// Field 13: fixed numeric value: 501
cout.WriteTag(13, WireFormat.WireType.Fixed32);
Assert.AreEqual(116, cout.Position);
cout.WriteSFixed32NoTag(501);
cout.WriteSFixed32(501);
Assert.AreEqual(120, cout.Position);
cout.Flush();
}
@ -405,17 +391,17 @@ namespace Google.Protobuf
// Field 1: numeric value: 500
cout.WriteTag(1, WireFormat.WireType.Varint);
Assert.AreEqual(1, cout.Position);
cout.WriteInt32NoTag(500);
cout.WriteInt32(500);
Assert.AreEqual(3, cout.Position);
//Field 2: length delimited 120 bytes
cout.WriteTag(2, WireFormat.WireType.LengthDelimited);
Assert.AreEqual(4, cout.Position);
cout.WriteBytesNoTag(ByteString.CopyFrom(child));
cout.WriteBytes(ByteString.CopyFrom(child));
Assert.AreEqual(125, cout.Position);
// Field 3: fixed numeric value: 500
cout.WriteTag(3, WireFormat.WireType.Fixed32);
Assert.AreEqual(126, cout.Position);
cout.WriteSFixed32NoTag(501);
cout.WriteSFixed32(501);
Assert.AreEqual(130, cout.Position);
cout.Flush();
}

@ -109,14 +109,15 @@ namespace Google.Protobuf.TestProtos {
public void WriteTo(pb::CodedOutputStream output) {
if (D != 0) {
output.WriteInt32(1, D);
output.WriteRawTag(8);
output.WriteInt32(D);
}
}
public int CalculateSize() {
int size = 0;
if (D != 0) {
size += pb::CodedOutputStream.ComputeInt32Size(1, D);
size += 1 + pb::CodedOutputStream.ComputeInt32Size(D);
}
return size;
}

@ -94,14 +94,15 @@ namespace Google.Protobuf.TestProtos {
public void WriteTo(pb::CodedOutputStream output) {
if (E != 0) {
output.WriteInt32(1, E);
output.WriteRawTag(8);
output.WriteInt32(E);
}
}
public int CalculateSize() {
int size = 0;
if (E != 0) {
size += pb::CodedOutputStream.ComputeInt32Size(1, E);
size += 1 + pb::CodedOutputStream.ComputeInt32Size(E);
}
return size;
}

@ -155,25 +155,27 @@ namespace UnitTest.Issues.TestProtos {
public void WriteTo(pb::CodedOutputStream output) {
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) {
output.WriteEnumArray(2, values_);
}
if (packedValues_.Count > 0) {
output.WritePackedEnumArray(3, packedValues_);
output.WriteRawTag(26);
output.WritePackedEnumArray(packedValues_);
}
}
public int CalculateSize() {
int size = 0;
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) {
int dataSize = 0;
foreach (global::UnitTest.Issues.TestProtos.NegativeEnum element in values_) {
dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);
dataSize += pb::CodedOutputStream.ComputeEnumSize((int) element);
}
size += dataSize;
size += 1 * values_.Count;
@ -181,11 +183,10 @@ namespace UnitTest.Issues.TestProtos {
if (packedValues_.Count > 0) {
int dataSize = 0;
foreach (global::UnitTest.Issues.TestProtos.NegativeEnum element in packedValues_) {
dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);
dataSize += pb::CodedOutputStream.ComputeEnumSize((int) element);
}
size += dataSize;
size += 1;
size += pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);
size += 1 + pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);
}
return size;
}
@ -305,7 +306,7 @@ namespace UnitTest.Issues.TestProtos {
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 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 {
get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_DeprecatedFieldsMessage__Descriptor; }
}
@ -397,57 +398,62 @@ namespace UnitTest.Issues.TestProtos {
public void WriteTo(pb::CodedOutputStream output) {
if (PrimitiveValue != 0) {
output.WriteInt32(1, PrimitiveValue);
output.WriteRawTag(8);
output.WriteInt32(PrimitiveValue);
}
if (primitiveArray_.Count > 0) {
output.WritePackedInt32Array(2, primitiveArray_);
output.WriteRawTag(18);
output.WritePackedInt32Array(primitiveArray_);
}
if (messageValue_ != null) {
output.WriteMessage(3, MessageValue);
output.WriteRawTag(26);
output.WriteMessage(MessageValue);
}
if (messageArray_.Count > 0) {
output.WriteMessageArray(4, messageArray_);
}
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) {
output.WritePackedEnumArray(6, enumArray_);
output.WriteRawTag(50);
output.WritePackedEnumArray(enumArray_);
}
}
public int CalculateSize() {
int size = 0;
if (PrimitiveValue != 0) {
size += pb::CodedOutputStream.ComputeInt32Size(1, PrimitiveValue);
size += 1 + pb::CodedOutputStream.ComputeInt32Size(PrimitiveValue);
}
if (primitiveArray_.Count > 0) {
int dataSize = 0;
foreach (int element in primitiveArray_) {
dataSize += pb::CodedOutputStream.ComputeInt32SizeNoTag(element);
dataSize += pb::CodedOutputStream.ComputeInt32Size(element);
}
size += dataSize;
size += 1 + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize);
size += 1 + pb::CodedOutputStream.ComputeInt32Size(dataSize);
}
if (messageValue_ != null) {
size += pb::CodedOutputStream.ComputeMessageSize(3, MessageValue);
size += 1 + pb::CodedOutputStream.ComputeMessageSize(MessageValue);
}
if (messageArray_.Count > 0) {
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) {
size += pb::CodedOutputStream.ComputeEnumSize(5, (int) EnumValue);
size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) EnumValue);
}
if (enumArray_.Count > 0) {
int dataSize = 0;
foreach (global::UnitTest.Issues.TestProtos.DeprecatedEnum element in enumArray_) {
dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);
dataSize += pb::CodedOutputStream.ComputeEnumSize((int) element);
}
size += dataSize;
size += 1;
size += pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);
size += 1 + pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);
}
return size;
}
@ -568,14 +574,15 @@ namespace UnitTest.Issues.TestProtos {
public void WriteTo(pb::CodedOutputStream output) {
if (Item != 0) {
output.WriteInt32(1, Item);
output.WriteRawTag(8);
output.WriteInt32(Item);
}
}
public int CalculateSize() {
int size = 0;
if (Item != 0) {
size += pb::CodedOutputStream.ComputeInt32Size(1, Item);
size += 1 + pb::CodedOutputStream.ComputeInt32Size(Item);
}
return size;
}

@ -47,193 +47,13 @@ namespace Google.Protobuf
public sealed partial class CodedOutputStream
{
private const int LittleEndian64Size = 8;
private const int LittleEndian32Size = 4;
private const int LittleEndian32Size = 4;
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// double field, including the tag.
/// </summary>
public static int ComputeDoubleSize(int fieldNumber, double value)
{
return ComputeTagSize(fieldNumber) + LittleEndian64Size;
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// float field, including the tag.
/// </summary>
public static int ComputeFloatSize(int fieldNumber, float value)
{
return ComputeTagSize(fieldNumber) + LittleEndian32Size;
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// uint64 field, including the tag.
/// </summary>
public static int ComputeUInt64Size(int fieldNumber, ulong value)
{
return ComputeTagSize(fieldNumber) + ComputeRawVarint64Size(value);
}
/// <summary>
/// Compute the number of bytes that would be needed to encode an
/// int64 field, including the tag.
/// </summary>
public static int ComputeInt64Size(int fieldNumber, long value)
{
return ComputeTagSize(fieldNumber) + ComputeRawVarint64Size((ulong) value);
}
/// <summary>
/// Compute the number of bytes that would be needed to encode an
/// int32 field, including the tag.
/// </summary>
public static int ComputeInt32Size(int fieldNumber, int value)
{
return ComputeTagSize(fieldNumber) + ComputeInt32SizeNoTag(value);
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// fixed64 field, including the tag.
/// </summary>
public static int ComputeFixed64Size(int fieldNumber, ulong value)
{
return ComputeTagSize(fieldNumber) + LittleEndian64Size;
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// fixed32 field, including the tag.
/// </summary>
public static int ComputeFixed32Size(int fieldNumber, uint value)
{
return ComputeTagSize(fieldNumber) + LittleEndian32Size;
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// bool field, including the tag.
/// </summary>
public static int ComputeBoolSize(int fieldNumber, bool value)
{
return ComputeTagSize(fieldNumber) + 1;
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// string field, including the tag.
/// </summary>
public static int ComputeStringSize(int fieldNumber, String value)
{
int byteArraySize = UTF8.GetByteCount(value);
return ComputeTagSize(fieldNumber) +
ComputeRawVarint32Size((uint) byteArraySize) +
byteArraySize;
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// group field, including the tag.
/// </summary>
public static int ComputeGroupSize(int fieldNumber, IMessage value)
{
return ComputeTagSize(fieldNumber)*2 + value.CalculateSize();
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// group field represented by an UnknownFieldSet, including the tag.
/// </summary>
[Obsolete]
public static int ComputeUnknownGroupSize(int fieldNumber,
IMessage value)
{
return ComputeTagSize(fieldNumber)*2 + value.CalculateSize();
}
/// <summary>
/// Compute the number of bytes that would be needed to encode an
/// embedded message field, including the tag.
/// </summary>
public static int ComputeMessageSize(int fieldNumber, IMessage value)
{
int size = value.CalculateSize();
return ComputeTagSize(fieldNumber) + ComputeRawVarint32Size((uint) size) + size;
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// bytes field, including the tag.
/// </summary>
public static int ComputeBytesSize(int fieldNumber, ByteString value)
{
return ComputeTagSize(fieldNumber) +
ComputeRawVarint32Size((uint) value.Length) +
value.Length;
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// uint32 field, including the tag.
/// </summary>
public static int ComputeUInt32Size(int fieldNumber, uint value)
{
return ComputeTagSize(fieldNumber) + ComputeRawVarint32Size(value);
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// enum field, including the tag. The caller is responsible for
/// converting the enum value to its numeric value.
/// </summary>
public static int ComputeEnumSize(int fieldNumber, int value)
{
return ComputeTagSize(fieldNumber) + ComputeEnumSizeNoTag(value);
}
/// <summary>
/// Compute the number of bytes that would be needed to encode an
/// sfixed32 field, including the tag.
/// </summary>
public static int ComputeSFixed32Size(int fieldNumber, int value)
{
return ComputeTagSize(fieldNumber) + LittleEndian32Size;
}
/// <summary>
/// Compute the number of bytes that would be needed to encode an
/// sfixed64 field, including the tag.
/// </summary>
public static int ComputeSFixed64Size(int fieldNumber, long value)
{
return ComputeTagSize(fieldNumber) + LittleEndian64Size;
}
/// <summary>
/// Compute the number of bytes that would be needed to encode an
/// sint32 field, including the tag.
/// </summary>
public static int ComputeSInt32Size(int fieldNumber, int value)
{
return ComputeTagSize(fieldNumber) + ComputeRawVarint32Size(EncodeZigZag32(value));
}
/// <summary>
/// Compute the number of bytes that would be needed to encode an
/// sint64 field, including the tag.
/// </summary>
public static int ComputeSInt64Size(int fieldNumber, long value)
{
return ComputeTagSize(fieldNumber) + ComputeRawVarint64Size(EncodeZigZag64(value));
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// double field, including the tag.
/// </summary>
public static int ComputeDoubleSizeNoTag(double value)
public static int ComputeDoubleSize(double value)
{
return LittleEndian64Size;
}
@ -242,7 +62,7 @@ namespace Google.Protobuf
/// Compute the number of bytes that would be needed to encode a
/// float field, including the tag.
/// </summary>
public static int ComputeFloatSizeNoTag(float value)
public static int ComputeFloatSize(float value)
{
return LittleEndian32Size;
}
@ -251,7 +71,7 @@ namespace Google.Protobuf
/// Compute the number of bytes that would be needed to encode a
/// uint64 field, including the tag.
/// </summary>
public static int ComputeUInt64SizeNoTag(ulong value)
public static int ComputeUInt64Size(ulong value)
{
return ComputeRawVarint64Size(value);
}
@ -260,7 +80,7 @@ namespace Google.Protobuf
/// Compute the number of bytes that would be needed to encode an
/// int64 field, including the tag.
/// </summary>
public static int ComputeInt64SizeNoTag(long value)
public static int ComputeInt64Size(long value)
{
return ComputeRawVarint64Size((ulong) value);
}
@ -269,7 +89,7 @@ namespace Google.Protobuf
/// Compute the number of bytes that would be needed to encode an
/// int32 field, including the tag.
/// </summary>
public static int ComputeInt32SizeNoTag(int value)
public static int ComputeInt32Size(int value)
{
if (value >= 0)
{
@ -286,7 +106,7 @@ namespace Google.Protobuf
/// Compute the number of bytes that would be needed to encode a
/// fixed64 field, including the tag.
/// </summary>
public static int ComputeFixed64SizeNoTag(ulong value)
public static int ComputeFixed64Size(ulong value)
{
return LittleEndian64Size;
}
@ -295,7 +115,7 @@ namespace Google.Protobuf
/// Compute the number of bytes that would be needed to encode a
/// fixed32 field, including the tag.
/// </summary>
public static int ComputeFixed32SizeNoTag(uint value)
public static int ComputeFixed32Size(uint value)
{
return LittleEndian32Size;
}
@ -304,7 +124,7 @@ namespace Google.Protobuf
/// Compute the number of bytes that would be needed to encode a
/// bool field, including the tag.
/// </summary>
public static int ComputeBoolSizeNoTag(bool value)
public static int ComputeBoolSize(bool value)
{
return 1;
}
@ -313,7 +133,7 @@ namespace Google.Protobuf
/// Compute the number of bytes that would be needed to encode a
/// string field, including the tag.
/// </summary>
public static int ComputeStringSizeNoTag(String value)
public static int ComputeStringSize(String value)
{
int byteArraySize = UTF8.GetByteCount(value);
return ComputeRawVarint32Size((uint) byteArraySize) +
@ -324,7 +144,7 @@ namespace Google.Protobuf
/// Compute the number of bytes that would be needed to encode a
/// group field, including the tag.
/// </summary>
public static int ComputeGroupSizeNoTag(IMessage value)
public static int ComputeGroupSize(IMessage value)
{
return value.CalculateSize();
}
@ -333,7 +153,7 @@ namespace Google.Protobuf
/// Compute the number of bytes that would be needed to encode an
/// embedded message field, including the tag.
/// </summary>
public static int ComputeMessageSizeNoTag(IMessage value)
public static int ComputeMessageSize(IMessage value)
{
int size = value.CalculateSize();
return ComputeRawVarint32Size((uint) size) + size;
@ -343,7 +163,7 @@ namespace Google.Protobuf
/// Compute the number of bytes that would be needed to encode a
/// bytes field, including the tag.
/// </summary>
public static int ComputeBytesSizeNoTag(ByteString value)
public static int ComputeBytesSize(ByteString value)
{
return ComputeRawVarint32Size((uint) value.Length) +
value.Length;
@ -353,7 +173,7 @@ namespace Google.Protobuf
/// Compute the number of bytes that would be needed to encode a
/// uint32 field, including the tag.
/// </summary>
public static int ComputeUInt32SizeNoTag(uint value)
public static int ComputeUInt32Size(uint value)
{
return ComputeRawVarint32Size(value);
}
@ -363,17 +183,17 @@ namespace Google.Protobuf
/// enum field, including the tag. The caller is responsible for
/// converting the enum value to its numeric value.
/// </summary>
public static int ComputeEnumSizeNoTag(int value)
public static int ComputeEnumSize(int value)
{
// Currently just a pass-through, but it's nice to separate it logically.
return ComputeInt32SizeNoTag(value);
return ComputeInt32Size(value);
}
/// <summary>
/// Compute the number of bytes that would be needed to encode an
/// sfixed32 field, including the tag.
/// </summary>
public static int ComputeSFixed32SizeNoTag(int value)
public static int ComputeSFixed32Size(int value)
{
return LittleEndian32Size;
}
@ -382,7 +202,7 @@ namespace Google.Protobuf
/// Compute the number of bytes that would be needed to encode an
/// sfixed64 field, including the tag.
/// </summary>
public static int ComputeSFixed64SizeNoTag(long value)
public static int ComputeSFixed64Size(long value)
{
return LittleEndian64Size;
}
@ -391,7 +211,7 @@ namespace Google.Protobuf
/// Compute the number of bytes that would be needed to encode an
/// sint32 field, including the tag.
/// </summary>
public static int ComputeSInt32SizeNoTag(int value)
public static int ComputeSInt32Size(int value)
{
return ComputeRawVarint32Size(EncodeZigZag32(value));
}
@ -400,7 +220,7 @@ namespace Google.Protobuf
/// Compute the number of bytes that would be needed to encode an
/// sint64 field, including the tag.
/// </summary>
public static int ComputeSInt64SizeNoTag(long value)
public static int ComputeSInt64Size(long value)
{
return ComputeRawVarint64Size(EncodeZigZag64(value));
}

@ -143,248 +143,12 @@ namespace Google.Protobuf
}
}
#region Writing of tags and fields
/// <summary>
/// Writes a double field value, including tag, to the stream.
/// </summary>
public void WriteDouble(int fieldNumber, double value)
{
WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
WriteDoubleNoTag(value);
}
/// <summary>
/// Writes a float field value, including tag, to the stream.
/// </summary>
public void WriteFloat(int fieldNumber, float value)
{
WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
WriteFloatNoTag(value);
}
/// <summary>
/// Writes a uint64 field value, including tag, to the stream.
/// </summary>
public void WriteUInt64(int fieldNumber, ulong value)
{
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteRawVarint64(value);
}
/// <summary>
/// Writes an int64 field value, including tag, to the stream.
/// </summary>
public void WriteInt64(int fieldNumber, long value)
{
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteRawVarint64((ulong) value);
}
/// <summary>
/// Writes an int32 field value, including tag, to the stream.
/// </summary>
public void WriteInt32(int fieldNumber, int value)
{
WriteTag(fieldNumber, WireFormat.WireType.Varint);
if (value >= 0)
{
WriteRawVarint32((uint) value);
}
else
{
// Must sign-extend.
WriteRawVarint64((ulong) value);
}
}
/// <summary>
/// Writes a fixed64 field value, including tag, to the stream.
/// </summary>
public void WriteFixed64(int fieldNumber, ulong value)
{
WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
WriteRawLittleEndian64(value);
}
/// <summary>
/// Writes a fixed32 field value, including tag, to the stream.
/// </summary>
public void WriteFixed32(int fieldNumber, uint value)
{
WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
WriteRawLittleEndian32(value);
}
/// <summary>
/// Writes a bool field value, including tag, to the stream.
/// </summary>
public void WriteBool(int fieldNumber, bool value)
{
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteRawByte(value ? (byte) 1 : (byte) 0);
}
/// <summary>
/// Writes a string field value, including tag, to the stream.
/// </summary>
public void WriteString(int fieldNumber, string value)
{
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
// Optimise the case where we have enough space to write
// the string directly to the buffer, which should be common.
int length = UTF8.GetByteCount(value);
WriteRawVarint32((uint) length);
if (limit - position >= length)
{
if (length == value.Length) // Must be all ASCII...
{
for (int i = 0; i < length; i++)
{
buffer[position + i] = (byte)value[i];
}
}
else
{
UTF8.GetBytes(value, 0, value.Length, buffer, position);
}
position += length;
}
else
{
byte[] bytes = UTF8.GetBytes(value);
WriteRawBytes(bytes);
}
}
/// <summary>
/// Writes a group field value, including tag, to the stream.
/// </summary>
public void WriteGroup(int fieldNumber, IMessage value)
{
WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
value.WriteTo(this);
WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
}
public void WriteMessage(int fieldNumber, IMessage value)
{
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
WriteRawVarint32((uint) value.CalculateSize());
value.WriteTo(this);
}
public void WriteBytes(int fieldNumber, ByteString value)
{
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
WriteRawVarint32((uint) value.Length);
value.WriteRawBytesTo(this);
}
public void WriteUInt32(int fieldNumber, uint value)
{
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteRawVarint32(value);
}
public void WriteEnum(int fieldNumber, int value)
{
// Currently just a pass-through, but it's nice to separate it logically from WriteInt32.
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteInt32NoTag(value);
}
public void WriteSFixed32(int fieldNumber, int value)
{
WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
WriteRawLittleEndian32((uint) value);
}
public void WriteSFixed64(int fieldNumber, long value)
{
WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
WriteRawLittleEndian64((ulong) value);
}
public void WriteSInt32(int fieldNumber, int value)
{
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteRawVarint32(EncodeZigZag32(value));
}
public void WriteSInt64(int fieldNumber, long value)
{
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteRawVarint64(EncodeZigZag64(value));
}
#endregion
#region Writing of values without tags
// TODO(jonskeet): Remove this?
public void WriteFieldNoTag(FieldType fieldType, object value)
{
switch (fieldType)
{
case FieldType.String:
WriteStringNoTag((string) value);
break;
case FieldType.Message:
WriteMessageNoTag((IMessage) value);
break;
case FieldType.Group:
WriteGroupNoTag((IMessage) value);
break;
case FieldType.Bytes:
WriteBytesNoTag((ByteString) value);
break;
case FieldType.Bool:
WriteBoolNoTag((bool) value);
break;
case FieldType.Enum:
WriteEnumNoTag((int) value);
break;
case FieldType.Int32:
WriteInt32NoTag((int) value);
break;
case FieldType.Int64:
WriteInt64NoTag((long) value);
break;
case FieldType.UInt32:
WriteUInt32NoTag((uint) value);
break;
case FieldType.UInt64:
WriteUInt64NoTag((ulong) value);
break;
case FieldType.SInt32:
WriteSInt32NoTag((int) value);
break;
case FieldType.SInt64:
WriteSInt64NoTag((long) value);
break;
case FieldType.Fixed32:
WriteFixed32NoTag((uint) value);
break;
case FieldType.Fixed64:
WriteFixed64NoTag((ulong) value);
break;
case FieldType.SFixed32:
WriteSFixed32NoTag((int) value);
break;
case FieldType.SFixed64:
WriteSFixed64NoTag((long) value);
break;
case FieldType.Double:
WriteDoubleNoTag((double) value);
break;
case FieldType.Float:
WriteFloatNoTag((float) value);
break;
}
}
/// <summary>
/// Writes a double field value, including tag, to the stream.
/// </summary>
public void WriteDoubleNoTag(double value)
public void WriteDouble(double value)
{
WriteRawLittleEndian64((ulong)FrameworkPortability.DoubleToInt64(value));
}
@ -392,7 +156,7 @@ namespace Google.Protobuf
/// <summary>
/// Writes a float field value, without a tag, to the stream.
/// </summary>
public void WriteFloatNoTag(float value)
public void WriteFloat(float value)
{
byte[] rawBytes = BitConverter.GetBytes(value);
if (!BitConverter.IsLittleEndian)
@ -416,7 +180,7 @@ namespace Google.Protobuf
/// <summary>
/// Writes a uint64 field value, without a tag, to the stream.
/// </summary>
public void WriteUInt64NoTag(ulong value)
public void WriteUInt64(ulong value)
{
WriteRawVarint64(value);
}
@ -424,7 +188,7 @@ namespace Google.Protobuf
/// <summary>
/// Writes an int64 field value, without a tag, to the stream.
/// </summary>
public void WriteInt64NoTag(long value)
public void WriteInt64(long value)
{
WriteRawVarint64((ulong) value);
}
@ -432,7 +196,7 @@ namespace Google.Protobuf
/// <summary>
/// Writes an int32 field value, without a tag, to the stream.
/// </summary>
public void WriteInt32NoTag(int value)
public void WriteInt32(int value)
{
if (value >= 0)
{
@ -448,7 +212,7 @@ namespace Google.Protobuf
/// <summary>
/// Writes a fixed64 field value, without a tag, to the stream.
/// </summary>
public void WriteFixed64NoTag(ulong value)
public void WriteFixed64(ulong value)
{
WriteRawLittleEndian64(value);
}
@ -456,7 +220,7 @@ namespace Google.Protobuf
/// <summary>
/// Writes a fixed32 field value, without a tag, to the stream.
/// </summary>
public void WriteFixed32NoTag(uint value)
public void WriteFixed32(uint value)
{
WriteRawLittleEndian32(value);
}
@ -464,7 +228,7 @@ namespace Google.Protobuf
/// <summary>
/// Writes a bool field value, without a tag, to the stream.
/// </summary>
public void WriteBoolNoTag(bool value)
public void WriteBool(bool value)
{
WriteRawByte(value ? (byte) 1 : (byte) 0);
}
@ -472,485 +236,440 @@ namespace Google.Protobuf
/// <summary>
/// Writes a string field value, without a tag, to the stream.
/// </summary>
public void WriteStringNoTag(string value)
public void WriteString(string value)
{
// Optimise the case where we have enough space to write
// the string directly to the buffer, which should be common.
int length = Encoding.UTF8.GetByteCount(value);
WriteRawVarint32((uint) length);
int length = UTF8.GetByteCount(value);
WriteRawVarint32((uint)length);
if (limit - position >= length)
{
Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, position);
if (length == value.Length) // Must be all ASCII...
{
for (int i = 0; i < length; i++)
{
buffer[position + i] = (byte)value[i];
}
}
else
{
UTF8.GetBytes(value, 0, value.Length, buffer, position);
}
position += length;
}
else
{
byte[] bytes = Encoding.UTF8.GetBytes(value);
byte[] bytes = UTF8.GetBytes(value);
WriteRawBytes(bytes);
}
}
/// <summary>
/// Writes a group field value, without a tag, to the stream.
/// </summary>
public void WriteGroupNoTag(IMessage value)
{
value.WriteTo(this);
}
public void WriteMessageNoTag(IMessage value)
public void WriteMessage(IMessage value)
{
WriteRawVarint32((uint) value.CalculateSize());
value.WriteTo(this);
}
public void WriteBytesNoTag(ByteString value)
public void WriteBytes(ByteString value)
{
WriteRawVarint32((uint) value.Length);
value.WriteRawBytesTo(this);
}
public void WriteUInt32NoTag(uint value)
public void WriteUInt32(uint value)
{
WriteRawVarint32(value);
}
public void WriteEnumNoTag(int value)
public void WriteEnum(int value)
{
WriteInt32NoTag(value);
WriteInt32(value);
}
public void WriteSFixed32NoTag(int value)
public void WriteSFixed32(int value)
{
WriteRawLittleEndian32((uint) value);
}
public void WriteSFixed64NoTag(long value)
public void WriteSFixed64(long value)
{
WriteRawLittleEndian64((ulong) value);
}
public void WriteSInt32NoTag(int value)
public void WriteSInt32(int value)
{
WriteRawVarint32(EncodeZigZag32(value));
}
public void WriteSInt64NoTag(long value)
public void WriteSInt64(long value)
{
WriteRawVarint64(EncodeZigZag64(value));
}
#endregion
#region Write array members
#region Write array members, with fields.
public void WriteMessageArray<T>(int fieldNumber, RepeatedField<T> list)
where T : IMessage
{
if (list.Count == 0)
{
return;
}
foreach (T value in list)
{
WriteMessage(fieldNumber, value);
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
WriteMessage(value);
}
}
public void WriteStringArray(int fieldNumber, RepeatedField<string> list)
{
if (list.Count == 0)
{
return;
}
foreach (var value in list)
{
WriteString(fieldNumber, value);
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
WriteString(value);
}
}
public void WriteBytesArray(int fieldNumber, RepeatedField<ByteString> list)
{
if (list.Count == 0)
{
return;
}
foreach (var value in list)
{
WriteBytes(fieldNumber, value);
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
WriteBytes(value);
}
}
public void WriteBoolArray(int fieldNumber, RepeatedField<bool> list)
{
if (list.Count == 0)
{
return;
}
foreach (var value in list)
{
WriteBool(fieldNumber, value);
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteBool(value);
}
}
public void WriteInt32Array(int fieldNumber, RepeatedField<int> list)
{
if (list.Count == 0)
{
return;
}
foreach (var value in list)
{
WriteInt32(fieldNumber, value);
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteInt32(value);
}
}
public void WriteSInt32Array(int fieldNumber, RepeatedField<int> list)
{
if (list.Count == 0)
{
return;
}
foreach (var value in list)
{
WriteSInt32(fieldNumber, value);
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteSInt32(value);
}
}
public void WriteUInt32Array(int fieldNumber, RepeatedField<uint> list)
{
if (list.Count == 0)
{
return;
}
foreach (var value in list)
{
WriteUInt32(fieldNumber, value);
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteUInt32(value);
}
}
public void WriteFixed32Array(int fieldNumber, RepeatedField<uint> list)
{
if (list.Count == 0)
{
return;
}
foreach (var value in list)
{
WriteFixed32(fieldNumber, value);
WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
WriteFixed32(value);
}
}
public void WriteSFixed32Array(int fieldNumber, RepeatedField<int> list)
{
if (list.Count == 0)
{
return;
}
foreach (var value in list)
{
WriteSFixed32(fieldNumber, value);
WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
WriteSFixed32(value);
}
}
public void WriteInt64Array(int fieldNumber, RepeatedField<long> list)
{
if (list.Count == 0)
{
return;
}
foreach (var value in list)
{
WriteInt64(fieldNumber, value);
WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
WriteInt64(value);
}
}
public void WriteSInt64Array(int fieldNumber, RepeatedField<long> list)
{
if (list.Count == 0)
{
return;
}
foreach (var value in list)
{
WriteSInt64(fieldNumber, value);
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteSInt64(value);
}
}
public void WriteUInt64Array(int fieldNumber, RepeatedField<ulong> list)
{
if (list.Count == 0)
{
return;
}
foreach (var value in list)
{
WriteUInt64(fieldNumber, value);
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteUInt64(value);
}
}
public void WriteFixed64Array(int fieldNumber, RepeatedField<ulong> list)
{
if (list.Count == 0)
{
return;
}
foreach (var value in list)
{
WriteFixed64(fieldNumber, value);
WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
WriteFixed64(value);
}
}
public void WriteSFixed64Array(int fieldNumber, RepeatedField<long> list)
{
if (list.Count == 0)
{
return;
}
foreach (var value in list)
{
WriteSFixed64(fieldNumber, value);
WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
WriteSFixed64(value);
}
}
public void WriteDoubleArray(int fieldNumber, RepeatedField<double> list)
{
if (list.Count == 0)
{
return;
}
foreach (var value in list)
{
WriteDouble(fieldNumber, value);
WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
WriteDouble(value);
}
}
public void WriteFloatArray(int fieldNumber, RepeatedField<float> list)
{
if (list.Count == 0)
{
return;
}
foreach (var value in list)
{
WriteFloat(fieldNumber, value);
WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
WriteFloat(value);
}
}
public void WriteEnumArray<T>(int fieldNumber, RepeatedField<T> list)
where T : struct, IComparable, IFormattable
{
if (list.Count == 0)
{
return;
}
// Bit of a hack, to access the values as ints
var iterator = list.GetInt32Enumerator();
while (iterator.MoveNext())
{
WriteEnum(fieldNumber, iterator.Current);
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteEnum(iterator.Current);
}
}
#endregion
#region Raw tag writing
/// <summary>
/// Encodes and writes a tag.
/// </summary>
public void WriteTag(int fieldNumber, WireFormat.WireType type)
{
WriteRawVarint32(WireFormat.MakeTag(fieldNumber, type));
}
/// <summary>
/// Writes the given single-byte tag directly to the stream.
/// </summary>
public void WriteRawTag(byte b1)
{
WriteRawByte(b1);
}
/// <summary>
/// Writes the given two-byte tag directly to the stream.
/// </summary>
public void WriteRawTag(byte b1, byte b2)
{
WriteRawByte(b1);
WriteRawByte(b2);
}
/// <summary>
/// Writes the given three-byte tag directly to the stream.
/// </summary>
public void WriteRawTag(byte b1, byte b2, byte b3)
{
WriteRawByte(b1);
WriteRawByte(b2);
WriteRawByte(b3);
}
/// <summary>
/// Writes the given four-byte tag directly to the stream.
/// </summary>
public void WriteRawTag(byte b1, byte b2, byte b3, byte b4)
{
WriteRawByte(b1);
WriteRawByte(b2);
WriteRawByte(b3);
WriteRawByte(b4);
}
/// <summary>
/// Writes the given five-byte tag directly to the stream.
/// </summary>
public void WriteRawTag(byte b1, byte b2, byte b3, byte b4, byte b5)
{
WriteRawByte(b1);
WriteRawByte(b2);
WriteRawByte(b3);
WriteRawByte(b4);
WriteRawByte(b5);
}
#endregion
#region Write packed array members
// TODO(jonskeet): A lot of these are really inefficient, due to method group conversions. Fix!
public void WritePackedBoolArray(int fieldNumber, RepeatedField<bool> list)
// (Alternatively, add extension methods to RepeatedField, accepting the Write* methods via delegates too.)
public void WritePackedBoolArray(RepeatedField<bool> list)
{
if (list.Count == 0)
{
return;
}
uint size = (uint)list.Count;
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
WriteRawVarint32(size);
foreach (var value in list)
{
WriteBoolNoTag(value);
WriteBool(value);
}
}
public void WritePackedInt32Array(int fieldNumber, RepeatedField<int> list)
public void WritePackedInt32Array(RepeatedField<int> list)
{
if (list.Count == 0)
{
return;
}
uint size = list.CalculateSize(ComputeInt32SizeNoTag);
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
uint size = list.CalculateSize(ComputeInt32Size);
WriteRawVarint32(size);
foreach (var value in list)
{
WriteInt32NoTag(value);
WriteInt32(value);
}
}
public void WritePackedSInt32Array(int fieldNumber, RepeatedField<int> list)
public void WritePackedSInt32Array(RepeatedField<int> list)
{
if (list.Count == 0)
{
return;
}
uint size = list.CalculateSize(ComputeSInt32SizeNoTag);
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
uint size = list.CalculateSize(ComputeSInt32Size);
WriteRawVarint32(size);
foreach (var value in list)
{
WriteSInt32NoTag(value);
WriteSInt32(value);
}
}
public void WritePackedUInt32Array(int fieldNumber, RepeatedField<uint> list)
public void WritePackedUInt32Array(RepeatedField<uint> list)
{
if (list.Count == 0)
{
return;
}
uint size = list.CalculateSize(ComputeUInt32SizeNoTag);
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
uint size = list.CalculateSize(ComputeUInt32Size);
WriteRawVarint32(size);
foreach (var value in list)
{
WriteUInt32NoTag(value);
WriteUInt32(value);
}
}
public void WritePackedFixed32Array(int fieldNumber, RepeatedField<uint> list)
public void WritePackedFixed32Array(RepeatedField<uint> list)
{
if (list.Count == 0)
{
return;
}
uint size = (uint) list.Count * 4;
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
WriteRawVarint32(size);
foreach (var value in list)
{
WriteFixed32NoTag(value);
WriteFixed32(value);
}
}
public void WritePackedSFixed32Array(int fieldNumber, RepeatedField<int> list)
public void WritePackedSFixed32Array(RepeatedField<int> list)
{
if (list.Count == 0)
{
return;
}
uint size = (uint) list.Count * 4;
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
WriteRawVarint32(size);
foreach (var value in list)
{
WriteSFixed32NoTag(value);
WriteSFixed32(value);
}
}
public void WritePackedInt64Array(int fieldNumber, RepeatedField<long> list)
public void WritePackedInt64Array(RepeatedField<long> list)
{
if (list.Count == 0)
{
return;
}
uint size = list.CalculateSize(ComputeInt64SizeNoTag);
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
uint size = list.CalculateSize(ComputeInt64Size);
WriteRawVarint32(size);
foreach (var value in list)
{
WriteInt64NoTag(value);
WriteInt64(value);
}
}
public void WritePackedSInt64Array(int fieldNumber, RepeatedField<long> list)
public void WritePackedSInt64Array(RepeatedField<long> list)
{
if (list.Count == 0)
{
return;
}
uint size = list.CalculateSize(ComputeSInt64SizeNoTag);
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
uint size = list.CalculateSize(ComputeSInt64Size);
WriteRawVarint32(size);
foreach (var value in list)
{
WriteSInt64NoTag(value);
WriteSInt64(value);
}
}
public void WritePackedUInt64Array(int fieldNumber, RepeatedField<ulong> list)
public void WritePackedUInt64Array(RepeatedField<ulong> list)
{
if (list.Count == 0)
{
return;
}
uint size = list.CalculateSize(ComputeUInt64SizeNoTag);
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
uint size = list.CalculateSize(ComputeUInt64Size);
WriteRawVarint32(size);
foreach (var value in list)
{
WriteUInt64NoTag(value);
WriteUInt64(value);
}
}
public void WritePackedFixed64Array(int fieldNumber, RepeatedField<ulong> list)
public void WritePackedFixed64Array(RepeatedField<ulong> list)
{
if (list.Count == 0)
{
return;
}
uint size = (uint) list.Count * 8;
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
WriteRawVarint32(size);
foreach (var value in list)
{
WriteFixed64NoTag(value);
WriteFixed64(value);
}
}
public void WritePackedSFixed64Array(int fieldNumber, RepeatedField<long> list)
public void WritePackedSFixed64Array(RepeatedField<long> list)
{
if (list.Count == 0)
{
return;
}
uint size = (uint) list.Count * 8;
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
WriteRawVarint32(size);
foreach (var value in list)
{
WriteSFixed64NoTag(value);
WriteSFixed64(value);
}
}
public void WritePackedDoubleArray(int fieldNumber, RepeatedField<double> list)
public void WritePackedDoubleArray(RepeatedField<double> list)
{
if (list.Count == 0)
{
return;
}
uint size = (uint) list.Count * 8;
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
WriteRawVarint32(size);
foreach (var value in list)
{
WriteDoubleNoTag(value);
WriteDouble(value);
}
}
public void WritePackedFloatArray(int fieldNumber, RepeatedField<float> list)
public void WritePackedFloatArray(RepeatedField<float> list)
{
if (list.Count == 0)
{
return;
}
uint size = (uint) list.Count * 4;
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
WriteRawVarint32(size);
foreach (var value in list)
{
WriteFloatNoTag(value);
WriteFloat(value);
}
}
public void WritePackedEnumArray<T>(int fieldNumber, RepeatedField<T> list)
public void WritePackedEnumArray<T>(RepeatedField<T> list)
where T : struct, IComparable, IFormattable
{
if (list.Count == 0)
@ -962,29 +681,19 @@ namespace Google.Protobuf
uint size = 0;
while (iterator.MoveNext())
{
size += (uint) ComputeEnumSizeNoTag(iterator.Current);
size += (uint) ComputeEnumSize(iterator.Current);
}
iterator.Reset();
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
WriteRawVarint32(size);
while (iterator.MoveNext())
{
WriteEnumNoTag(iterator.Current);
WriteEnum(iterator.Current);
}
}
#endregion
#region Underlying writing primitives
/// <summary>
/// Encodes and writes a tag.
/// </summary>
public void WriteTag(int fieldNumber, WireFormat.WireType type)
{
WriteRawVarint32(WireFormat.MakeTag(fieldNumber, type));
}
/// <summary>
/// Writes a 32 bit value as a varint. The fast route is taken when
/// there's enough buffer space left to whizz through without checking

@ -61,7 +61,8 @@ void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) {
void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
printer->Print(variables_,
"if ($has_property_check$) {\n"
" output.WriteEnum($number$, (int) $property_name$);\n"
" output.WriteRawTag($tag_bytes$);\n"
" output.WriteEnum((int) $property_name$);\n"
"}\n");
}
@ -69,7 +70,7 @@ void EnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print(
variables_,
"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");
}
@ -93,7 +94,8 @@ void EnumOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
" output.WriteEnum($number$, (int) $property_name$);\n"
" output.WriteRawTag($tag_bytes$);\n"
" output.WriteEnum((int) $property_name$);\n"
"}\n");
}
@ -101,7 +103,7 @@ void EnumOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print(
variables_,
"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");
}

@ -35,6 +35,7 @@
#include <google/protobuf/compiler/plugin.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/stubs/strutil.h>
@ -55,8 +56,18 @@ void FieldGeneratorBase::SetCommonFieldVariables(
// 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
// never effects the tag size.
int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type());
(*variables)["tag_size"] = SimpleItoa(tagSize);
int tag_size = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type());
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)["type_name"] = type_name();
(*variables)["name"] = name();

@ -92,11 +92,11 @@ void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) {
}
void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
// TODO(jonskeet): Why are we using array access instead of a literal here?
printer->Print(
variables_,
"if ($has_property_check$) {\n"
" output.WriteMessage($number$, $property_name$);\n"
" output.WriteRawTag($tag_bytes$);\n"
" output.WriteMessage($property_name$);\n"
"}\n");
}
@ -104,7 +104,7 @@ void MessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
" size += pb::CodedOutputStream.ComputeMessageSize($number$, $property_name$);\n"
" size += $tag_size$ + pb::CodedOutputStream.ComputeMessageSize($property_name$);\n"
"}\n");
}

@ -105,16 +105,29 @@ void PrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
printer->Print(
variables_,
"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");
}
void PrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
" size += pb::CodedOutputStream.Compute$capitalized_type_name$Size($number$, $property_name$);\n"
"}\n");
"if ($has_property_check$) {\n");
printer->Indent();
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) {
@ -173,7 +186,7 @@ void PrimitiveOneofFieldGenerator::WriteToString(io::Printer* printer) {
void PrimitiveOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
printer->Print(
variables_,
"$property_name$ = input.Read$capitalized_type_name$()\n;");
"$property_name$ = input.Read$capitalized_type_name$();\n");
}
} // namespace csharp

@ -82,9 +82,20 @@ void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer) {
void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($name$_.Count > 0) {\n"
" output.Write$packed$EnumArray($number$, $name$_);\n"
"}\n");
"if ($name$_.Count > 0) {\n");
printer->Indent();
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) {
@ -97,14 +108,13 @@ void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer
printer->Print(
variables_,
"foreach ($type_name$ element in $name$_) {\n"
" dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);\n"
" dataSize += pb::CodedOutputStream.ComputeEnumSize((int) element);\n"
"}\n"
"size += dataSize;\n");
int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type());
if (descriptor_->is_packed()) {
printer->Print(
"size += $tag_size$;\n"
"size += pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);\n",
"size += $tag_size$ + pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);\n",
"tag_size", SimpleItoa(tagSize));
} else {
printer->Print(

@ -79,8 +79,8 @@ void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer) {
}
void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
// TODO(jonskeet): Originally, this checked for Count > 0 first.
// The Write* call should make that cheap though - no need to generate it every time.
// TODO(jonskeet): Bake the foreach loop into the generated code? We lose the
// advantage of knowing the tag bytes this way :(
printer->Print(
variables_,
"if ($name$_.Count > 0) {\n"
@ -89,13 +89,13 @@ void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* print
}
void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
// TODO(jonskeet): Put this into CodedOutputStream.
printer->Print(
variables_,
"if ($name$_.Count > 0) {\n"
" foreach ($type_name$ element in $name$_) {\n"
" size += pb::CodedOutputStream.ComputeMessageSize($number$, element);\n"
" size += pb::CodedOutputStream.ComputeMessageSize(element);\n"
" }\n"
" size += $tag_size$ * $name$_.Count;\n"
"}\n");
}

@ -82,9 +82,20 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode(
io::Printer* printer) {
printer->Print(
variables_,
"if ($name$_.Count > 0) {\n"
" output.Write$packed$$capitalized_type_name$Array($number$, $name$_);\n"
"}\n");
"if ($name$_.Count > 0) {\n");
printer->Indent();
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(
@ -100,7 +111,7 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode(
printer->Print(
variables_,
"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");
} else {
printer->Print(
@ -111,7 +122,7 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode(
int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type());
if (descriptor_->is_packed()) {
printer->Print(
"size += $tag_size$ + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize);\n",
"size += $tag_size$ + pb::CodedOutputStream.ComputeInt32Size(dataSize);\n",
"tag_size", SimpleItoa(tagSize));
} else {
printer->Print(

@ -290,7 +290,7 @@ class LIBPROTOBUF_EXPORT UnknownFieldSetFieldSkipper : public FieldSkipper {
inline WireFormatLite::WireType WireFormat::WireTypeForField(
const FieldDescriptor* field) {
if (field->options().packed()) {
if (field->is_packed()) {
return WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
} else {
return WireTypeForFieldType(field->type());

Loading…
Cancel
Save