Merge pull request #560 from jskeet/csharp-repeated

Large changes to repeated field handling
pull/577/head
Jon Skeet 10 years ago
commit 4ae9b6c0d1
  1. 30
      csharp/src/AddressBook/Addressbook.cs
  2. 54
      csharp/src/ProtocolBuffers.Test/CodedInputStreamExtensions.cs
  3. 134
      csharp/src/ProtocolBuffers.Test/CodedInputStreamTest.cs
  4. 91
      csharp/src/ProtocolBuffers.Test/CodedOutputStreamTest.cs
  5. 291
      csharp/src/ProtocolBuffers.Test/Collections/RepeatedFieldTest.cs
  6. 63
      csharp/src/ProtocolBuffers.Test/FieldCodecTest.cs
  7. 133
      csharp/src/ProtocolBuffers.Test/GeneratedMessageTest.cs
  8. 2
      csharp/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
  9. 42
      csharp/src/ProtocolBuffers.Test/SampleEnum.cs
  10. 89
      csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs
  11. 1038
      csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs
  12. 584
      csharp/src/ProtocolBuffers/CodedInputStream.cs
  13. 51
      csharp/src/ProtocolBuffers/CodedOutputStream.ComputeSize.cs
  14. 416
      csharp/src/ProtocolBuffers/CodedOutputStream.cs
  15. 10
      csharp/src/ProtocolBuffers/Collections/MapField.cs
  16. 2
      csharp/src/ProtocolBuffers/Collections/ReadOnlyDictionary.cs
  17. 185
      csharp/src/ProtocolBuffers/Collections/RepeatedField.cs
  18. 466
      csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs
  19. 59
      csharp/src/ProtocolBuffers/FieldCodec.cs
  20. 2
      csharp/src/ProtocolBuffers/MessageExtensions.cs
  21. 7
      csharp/src/ProtocolBuffers/Properties/AssemblyInfo.cs
  22. 36
      csharp/src/ProtocolBuffers/WireFormat.cs
  23. 47
      src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
  24. 19
      src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
  25. 63
      src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc

@ -131,6 +131,8 @@ namespace Google.Protobuf.Examples.AddressBook {
}
public const int PhoneFieldNumber = 4;
private static readonly pb::FieldCodec<global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber> _repeated_phone_codec
= pb::FieldCodec.ForMessage(34, global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber.Parser);
private readonly pbc::RepeatedField<global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber> phone_ = new pbc::RepeatedField<global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber>();
public pbc::RepeatedField<global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber> Phone {
get { return phone_; }
@ -176,9 +178,7 @@ namespace Google.Protobuf.Examples.AddressBook {
output.WriteRawTag(26);
output.WriteString(Email);
}
if (phone_.Count > 0) {
output.WriteMessageArray(4, phone_);
}
phone_.WriteTo(output, _repeated_phone_codec);
}
public int CalculateSize() {
@ -192,12 +192,7 @@ namespace Google.Protobuf.Examples.AddressBook {
if (Email.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Email);
}
if (phone_.Count > 0) {
foreach (global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber element in phone_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 1 * phone_.Count;
}
size += phone_.CalculateSize(_repeated_phone_codec);
return size;
}
@ -241,7 +236,7 @@ namespace Google.Protobuf.Examples.AddressBook {
break;
}
case 34: {
input.ReadMessageArray(phone_, global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber.Parser);
phone_.AddEntriesFrom(input, _repeated_phone_codec);
break;
}
}
@ -437,6 +432,8 @@ namespace Google.Protobuf.Examples.AddressBook {
}
public const int PersonFieldNumber = 1;
private static readonly pb::FieldCodec<global::Google.Protobuf.Examples.AddressBook.Person> _repeated_person_codec
= pb::FieldCodec.ForMessage(10, global::Google.Protobuf.Examples.AddressBook.Person.Parser);
private readonly pbc::RepeatedField<global::Google.Protobuf.Examples.AddressBook.Person> person_ = new pbc::RepeatedField<global::Google.Protobuf.Examples.AddressBook.Person>();
public pbc::RepeatedField<global::Google.Protobuf.Examples.AddressBook.Person> Person {
get { return person_; }
@ -464,19 +461,12 @@ namespace Google.Protobuf.Examples.AddressBook {
}
public void WriteTo(pb::CodedOutputStream output) {
if (person_.Count > 0) {
output.WriteMessageArray(1, person_);
}
person_.WriteTo(output, _repeated_person_codec);
}
public int CalculateSize() {
int size = 0;
if (person_.Count > 0) {
foreach (global::Google.Protobuf.Examples.AddressBook.Person element in person_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 1 * person_.Count;
}
size += person_.CalculateSize(_repeated_person_codec);
return size;
}
@ -499,7 +489,7 @@ namespace Google.Protobuf.Examples.AddressBook {
}
break;
case 10: {
input.ReadMessageArray(person_, global::Google.Protobuf.Examples.AddressBook.Person.Parser);
person_.AddEntriesFrom(input, _repeated_person_codec);
break;
}
}

@ -0,0 +1,54 @@
#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
// Copyright 2015 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using NUnit.Framework;
namespace Google.Protobuf
{
internal static class CodedInputStreamExtensions
{
public static void AssertNextTag(this CodedInputStream input, uint expectedTag)
{
uint tag;
Assert.IsTrue(input.ReadTag(out tag));
Assert.AreEqual(expectedTag, tag);
}
public static T ReadMessage<T>(this CodedInputStream stream, MessageParser<T> parser)
where T : IMessage<T>
{
var message = parser.CreateTemplate();
stream.ReadMessage(message);
return message;
}
}
}

@ -35,10 +35,8 @@
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using Google.Protobuf.Collections;
using Google.Protobuf.Descriptors;
using Google.Protobuf.TestProtos;
using NUnit.Framework;
@ -62,7 +60,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Parses the given bytes using ReadRawVarint32() and ReadRawVarint64() and
/// Parses the given bytes using ReadRawVarint32() and ReadRawVarint64()
/// </summary>
private static void AssertReadVarint(byte[] data, ulong value)
{
@ -232,66 +230,26 @@ namespace Google.Protobuf
Assert.AreEqual(0x7FFFFFFFFFFFFFFFL, CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFEL));
Assert.AreEqual(unchecked((long) 0x8000000000000000L), CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFFL));
}
/*
[Test]
public void ReadWholeMessage()
public void ReadWholeMessage_VaryingBlockSizes()
{
TestAllTypes message = TestUtil.GetAllSet();
TestAllTypes message = GeneratedMessageTest.GetSampleMessage();
byte[] rawBytes = message.ToByteArray();
Assert.AreEqual(rawBytes.Length, message.SerializedSize);
TestAllTypes message2 = TestAllTypes.ParseFrom(rawBytes);
TestUtil.AssertAllFieldsSet(message2);
Assert.AreEqual(rawBytes.Length, message.CalculateSize());
TestAllTypes message2 = TestAllTypes.Parser.ParseFrom(rawBytes);
Assert.AreEqual(message, message2);
// Try different block sizes.
for (int blockSize = 1; blockSize < 256; blockSize *= 2)
{
message2 = TestAllTypes.ParseFrom(new SmallBlockInputStream(rawBytes, blockSize));
TestUtil.AssertAllFieldsSet(message2);
message2 = TestAllTypes.Parser.ParseFrom(new SmallBlockInputStream(rawBytes, blockSize));
Assert.AreEqual(message, message2);
}
}
[Test]
public void SkipWholeMessage()
{
TestAllTypes message = TestUtil.GetAllSet();
byte[] rawBytes = message.ToByteArray();
// Create two parallel inputs. Parse one as unknown fields while using
// skipField() to skip each field on the other. Expect the same tags.
CodedInputStream input1 = CodedInputStream.CreateInstance(rawBytes);
CodedInputStream input2 = CodedInputStream.CreateInstance(rawBytes);
UnknownFieldSet.Builder unknownFields = UnknownFieldSet.CreateBuilder();
uint tag;
string name;
while (input1.ReadTag(out tag, out name))
{
uint tag2;
Assert.IsTrue(input2.ReadTag(out tag2, out name));
Assert.AreEqual(tag, tag2);
unknownFields.MergeFieldFrom(tag, input1);
input2.SkipField();
}
}*/
/// <summary>
/// Test that a bug in SkipRawBytes has been fixed: if the skip
/// skips exactly up to a limit, this should bnot break things
/// </summary>
[Test]
public void SkipRawBytesBug()
{
byte[] rawBytes = new byte[] {1, 2};
CodedInputStream input = CodedInputStream.CreateInstance(rawBytes);
int limit = input.PushLimit(1);
input.SkipRawBytes(1);
input.PopLimit(limit);
Assert.AreEqual(2, input.ReadRawByte());
}
/*
public void ReadHugeBlob()
{
// Allocate and initialize a 1MB blob.
@ -302,24 +260,15 @@ namespace Google.Protobuf
}
// Make a message containing it.
TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
TestUtil.SetAllFields(builder);
builder.SetOptionalBytes(ByteString.CopyFrom(blob));
TestAllTypes message = builder.Build();
var message = new TestAllTypes { SingleBytes = ByteString.CopyFrom(blob) };
// Serialize and parse it. Make sure to parse from an InputStream, not
// directly from a ByteString, so that CodedInputStream uses buffered
// reading.
TestAllTypes message2 = TestAllTypes.ParseFrom(message.ToByteString().CreateCodedInput());
TestAllTypes message2 = TestAllTypes.Parser.ParseFrom(message.ToByteString());
Assert.AreEqual(message.OptionalBytes, message2.OptionalBytes);
// Make sure all the other fields were parsed correctly.
TestAllTypes message3 = TestAllTypes.CreateBuilder(message2)
.SetOptionalBytes(TestUtil.GetAllSet().OptionalBytes)
.Build();
TestUtil.AssertAllFieldsSet(message3);
}*/
Assert.AreEqual(message, message2);
}
[Test]
public void ReadMaliciouslyLargeBlob()
@ -461,66 +410,15 @@ namespace Google.Protobuf
}
}
enum TestNegEnum { None = 0, Value = -2 }
[Test]
public void TestNegativeEnum()
{
byte[] bytes = new byte[10] { 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01 };
byte[] bytes = { 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01 };
CodedInputStream input = CodedInputStream.CreateInstance(bytes);
Assert.AreEqual((int)TestNegEnum.Value, input.ReadEnum());
Assert.AreEqual((int)SampleEnum.NegativeValue, input.ReadEnum());
Assert.IsTrue(input.IsAtEnd);
}
[Test]
public void TestNegativeEnumPackedArray()
{
int arraySize = 1 + (10 * 5);
int msgSize = 1 + 1 + arraySize;
byte[] bytes = new byte[msgSize];
CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
output.WriteTag(8, WireFormat.WireType.LengthDelimited);
output.WritePackedInt32Array(new RepeatedField<int> { 0, -1, -2, -3, -4, -5 });
Assert.AreEqual(0, output.SpaceLeft);
CodedInputStream input = CodedInputStream.CreateInstance(bytes);
uint tag;
Assert.IsTrue(input.ReadTag(out tag));
RepeatedField<TestNegEnum> values = new RepeatedField<TestNegEnum>();
input.ReadEnumArray(values);
Assert.AreEqual(6, values.Count);
Assert.AreEqual(TestNegEnum.None, values[0]);
Assert.AreEqual(TestNegEnum.Value, values[2]);
// TODO(jonskeet): Test unknown value preservation
}
[Test]
public void TestNegativeEnumArray()
{
int arraySize = 1 + 1 + (11 * 5);
int msgSize = arraySize;
byte[] bytes = new byte[msgSize];
CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
output.WriteInt32Array(8, new RepeatedField<int> { 0, -1, -2, -3, -4, -5 });
Assert.AreEqual(0, output.SpaceLeft);
CodedInputStream input = CodedInputStream.CreateInstance(bytes);
uint tag;
Assert.IsTrue(input.ReadTag(out tag));
RepeatedField<TestNegEnum> values = new RepeatedField<TestNegEnum>();
input.ReadEnumArray(values);
Assert.AreEqual(6, values.Count);
Assert.AreEqual(TestNegEnum.None, values[0]);
Assert.AreEqual(TestNegEnum.Value, values[2]);
// TODO(jonskeet): Test unknown value preservation
}
//Issue 71: CodedInputStream.ReadBytes go to slow path unnecessarily
[Test]
public void TestSlowPathAvoidance()

@ -35,9 +35,8 @@
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using Google.Protobuf.Collections;
using Google.Protobuf.TestProtos;
using NUnit.Framework;
namespace Google.Protobuf
@ -195,42 +194,24 @@ namespace Google.Protobuf
0x9abcdef012345678UL);
}
/*
[Test]
public void WriteWholeMessage()
public void WriteWholeMessage_VaryingBlockSizes()
{
TestAllTypes message = TestUtil.GetAllSet();
TestAllTypes message = GeneratedMessageTest.GetSampleMessage();
byte[] rawBytes = message.ToByteArray();
TestUtil.AssertEqualBytes(TestUtil.GoldenMessage.ToByteArray(), rawBytes);
// Try different block sizes.
for (int blockSize = 1; blockSize < 256; blockSize *= 2)
{
MemoryStream rawOutput = new MemoryStream();
CodedOutputStream output =
CodedOutputStream.CreateInstance(rawOutput, blockSize);
CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput, blockSize);
message.WriteTo(output);
output.Flush();
TestUtil.AssertEqualBytes(rawBytes, rawOutput.ToArray());
Assert.AreEqual(rawBytes, rawOutput.ToArray());
}
}
/// <summary>
/// Tests writing a whole message with every packed field type. Ensures the
/// wire format of packed fields is compatible with C++.
/// </summary>
[Test]
public void WriteWholePackedFieldsMessage()
{
TestPackedTypes message = TestUtil.GetPackedSet();
byte[] rawBytes = message.ToByteArray();
TestUtil.AssertEqualBytes(TestUtil.GetGoldenPackedFieldsMessage().ToByteArray(),
rawBytes);
}
*/
[Test]
public void EncodeZigZag32()
{
@ -296,66 +277,16 @@ namespace Google.Protobuf
public void TestNegativeEnumNoTag()
{
Assert.AreEqual(10, CodedOutputStream.ComputeInt32Size(-2));
Assert.AreEqual(10, CodedOutputStream.ComputeEnumSize((int) TestNegEnum.Value));
Assert.AreEqual(10, CodedOutputStream.ComputeEnumSize((int) SampleEnum.NegativeValue));
byte[] bytes = new byte[10];
CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
output.WriteEnum((int) TestNegEnum.Value);
output.WriteEnum((int) SampleEnum.NegativeValue);
Assert.AreEqual(0, output.SpaceLeft);
Assert.AreEqual("FE-FF-FF-FF-FF-FF-FF-FF-FF-01", BitConverter.ToString(bytes));
}
enum TestNegEnum { None = 0, Value = -2 }
[Test]
public void TestNegativeEnumArrayPacked()
{
int arraySize = 1 + (10 * 5);
int msgSize = 1 + 1 + arraySize;
byte[] bytes = new byte[msgSize];
CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
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);
CodedInputStream input = CodedInputStream.CreateInstance(bytes);
uint tag;
Assert.IsTrue(input.ReadTag(out tag));
List<int> values = new List<int>();
input.ReadInt32Array(values);
Assert.AreEqual(6, values.Count);
for (int i = 0; i > -6; i--)
Assert.AreEqual(i, values[Math.Abs(i)]);
}
[Test]
public void TestNegativeEnumArray()
{
int arraySize = 1 + 1 + (11 * 5);
int msgSize = arraySize;
byte[] bytes = new byte[msgSize];
CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
output.WriteEnumArray(8, new RepeatedField<TestNegEnum> {
0, (TestNegEnum) (-1), TestNegEnum.Value, (TestNegEnum) (-3), (TestNegEnum) (-4), (TestNegEnum) (-5) });
Assert.AreEqual(0, output.SpaceLeft);
CodedInputStream input = CodedInputStream.CreateInstance(bytes);
uint tag;
Assert.IsTrue(input.ReadTag(out tag));
List<int> values = new List<int>();
input.ReadInt32Array(values);
Assert.AreEqual(6, values.Count);
for (int i = 0; i > -6; i--)
Assert.AreEqual(i, values[Math.Abs(i)]);
}
[Test]
public void TestCodedInputOutputPosition()
{
@ -405,7 +336,7 @@ namespace Google.Protobuf
Assert.AreEqual(130, cout.Position);
cout.Flush();
}
//Now test Input stream:
// Now test Input stream:
{
CodedInputStream cin = CodedInputStream.CreateInstance(new MemoryStream(bytes), new byte[50]);
uint tag;
@ -418,8 +349,8 @@ namespace Google.Protobuf
//Field 2:
Assert.IsTrue(cin.ReadTag(out tag) && tag >> 3 == 2);
Assert.AreEqual(4, cin.Position);
uint childlen = cin.ReadRawVarint32();
Assert.AreEqual(120u, childlen);
int childlen = cin.ReadLength();
Assert.AreEqual(120, childlen);
Assert.AreEqual(5, cin.Position);
int oldlimit = cin.PushLimit((int)childlen);
Assert.AreEqual(5, cin.Position);

@ -1,5 +1,39 @@
using System;
#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
// Copyright 2015 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Google.Protobuf.TestProtos;
using NUnit.Framework;
@ -89,5 +123,260 @@ namespace Google.Protobuf.Collections
var clone = list.Clone();
clone[0] = 1;
}
[Test]
public void AddEntriesFrom_PackedInt32()
{
uint packedTag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
var stream = new MemoryStream();
var output = CodedOutputStream.CreateInstance(stream);
var length = CodedOutputStream.ComputeInt32Size(10)
+ CodedOutputStream.ComputeInt32Size(999)
+ CodedOutputStream.ComputeInt32Size(-1000);
output.WriteTag(packedTag);
output.WriteRawVarint32((uint) length);
output.WriteInt32(10);
output.WriteInt32(999);
output.WriteInt32(-1000);
output.Flush();
stream.Position = 0;
// Deliberately "expecting" a non-packed tag, but we detect that the data is
// actually packed.
uint nonPackedTag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
var field = new RepeatedField<int>();
var input = CodedInputStream.CreateInstance(stream);
input.AssertNextTag(packedTag);
field.AddEntriesFrom(input, FieldCodec.ForInt32(nonPackedTag));
CollectionAssert.AreEqual(new[] { 10, 999, -1000 }, field);
Assert.IsTrue(input.IsAtEnd);
}
[Test]
public void AddEntriesFrom_NonPackedInt32()
{
uint nonPackedTag = WireFormat.MakeTag(10, WireFormat.WireType.Varint);
var stream = new MemoryStream();
var output = CodedOutputStream.CreateInstance(stream);
output.WriteTag(nonPackedTag);
output.WriteInt32(10);
output.WriteTag(nonPackedTag);
output.WriteInt32(999);
output.WriteTag(nonPackedTag);
output.WriteInt32(-1000); // Just for variety...
output.Flush();
stream.Position = 0;
// Deliberately "expecting" a packed tag, but we detect that the data is
// actually not packed.
uint packedTag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
var field = new RepeatedField<int>();
var input = CodedInputStream.CreateInstance(stream);
input.AssertNextTag(nonPackedTag);
field.AddEntriesFrom(input, FieldCodec.ForInt32(packedTag));
CollectionAssert.AreEqual(new[] { 10, 999, -1000 }, field);
Assert.IsTrue(input.IsAtEnd);
}
[Test]
public void AddEntriesFrom_String()
{
uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
var stream = new MemoryStream();
var output = CodedOutputStream.CreateInstance(stream);
output.WriteTag(tag);
output.WriteString("Foo");
output.WriteTag(tag);
output.WriteString("");
output.WriteTag(tag);
output.WriteString("Bar");
output.Flush();
stream.Position = 0;
var field = new RepeatedField<string>();
var input = CodedInputStream.CreateInstance(stream);
input.AssertNextTag(tag);
field.AddEntriesFrom(input, FieldCodec.ForString(tag));
CollectionAssert.AreEqual(new[] { "Foo", "", "Bar" }, field);
Assert.IsTrue(input.IsAtEnd);
}
[Test]
public void AddEntriesFrom_Message()
{
var message1 = new ForeignMessage { C = 2000 };
var message2 = new ForeignMessage { C = -250 };
uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
var stream = new MemoryStream();
var output = CodedOutputStream.CreateInstance(stream);
output.WriteTag(tag);
output.WriteMessage(message1);
output.WriteTag(tag);
output.WriteMessage(message2);
output.Flush();
stream.Position = 0;
var field = new RepeatedField<ForeignMessage>();
var input = CodedInputStream.CreateInstance(stream);
input.AssertNextTag(tag);
field.AddEntriesFrom(input, FieldCodec.ForMessage(tag, ForeignMessage.Parser));
CollectionAssert.AreEqual(new[] { message1, message2}, field);
Assert.IsTrue(input.IsAtEnd);
}
[Test]
public void WriteTo_PackedInt32()
{
uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
var field = new RepeatedField<int> { 10, 1000, 1000000 };
var stream = new MemoryStream();
var output = CodedOutputStream.CreateInstance(stream);
field.WriteTo(output, FieldCodec.ForInt32(tag));
output.Flush();
stream.Position = 0;
var input = CodedInputStream.CreateInstance(stream);
input.AssertNextTag(tag);
var length = input.ReadLength();
Assert.AreEqual(10, input.ReadInt32());
Assert.AreEqual(1000, input.ReadInt32());
Assert.AreEqual(1000000, input.ReadInt32());
Assert.IsTrue(input.IsAtEnd);
Assert.AreEqual(1 + CodedOutputStream.ComputeLengthSize(length) + length, stream.Length);
}
[Test]
public void WriteTo_NonPackedInt32()
{
uint tag = WireFormat.MakeTag(10, WireFormat.WireType.Varint);
var field = new RepeatedField<int> { 10, 1000, 1000000};
var stream = new MemoryStream();
var output = CodedOutputStream.CreateInstance(stream);
field.WriteTo(output, FieldCodec.ForInt32(tag));
output.Flush();
stream.Position = 0;
var input = CodedInputStream.CreateInstance(stream);
input.AssertNextTag(tag);
Assert.AreEqual(10, input.ReadInt32());
input.AssertNextTag(tag);
Assert.AreEqual(1000, input.ReadInt32());
input.AssertNextTag(tag);
Assert.AreEqual(1000000, input.ReadInt32());
Assert.IsTrue(input.IsAtEnd);
}
[Test]
public void WriteTo_String()
{
uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
var field = new RepeatedField<string> { "Foo", "", "Bar" };
var stream = new MemoryStream();
var output = CodedOutputStream.CreateInstance(stream);
field.WriteTo(output, FieldCodec.ForString(tag));
output.Flush();
stream.Position = 0;
var input = CodedInputStream.CreateInstance(stream);
input.AssertNextTag(tag);
Assert.AreEqual("Foo", input.ReadString());
input.AssertNextTag(tag);
Assert.AreEqual("", input.ReadString());
input.AssertNextTag(tag);
Assert.AreEqual("Bar", input.ReadString());
Assert.IsTrue(input.IsAtEnd);
}
[Test]
public void WriteTo_Message()
{
var message1 = new ForeignMessage { C = 20 };
var message2 = new ForeignMessage { C = 25 };
uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
var field = new RepeatedField<ForeignMessage> { message1, message2 };
var stream = new MemoryStream();
var output = CodedOutputStream.CreateInstance(stream);
field.WriteTo(output, FieldCodec.ForMessage(tag, ForeignMessage.Parser));
output.Flush();
stream.Position = 0;
var input = CodedInputStream.CreateInstance(stream);
input.AssertNextTag(tag);
Assert.AreEqual(message1, input.ReadMessage(ForeignMessage.Parser));
input.AssertNextTag(tag);
Assert.AreEqual(message2, input.ReadMessage(ForeignMessage.Parser));
Assert.IsTrue(input.IsAtEnd);
}
[Test]
public void TestNegativeEnumArray()
{
int arraySize = 1 + 1 + (11 * 5);
int msgSize = arraySize;
byte[] bytes = new byte[msgSize];
CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
uint tag = WireFormat.MakeTag(8, WireFormat.WireType.Varint);
for (int i = 0; i >= -5; i--)
{
output.WriteTag(tag);
output.WriteEnum(i);
}
Assert.AreEqual(0, output.SpaceLeft);
CodedInputStream input = CodedInputStream.CreateInstance(bytes);
Assert.IsTrue(input.ReadTag(out tag));
RepeatedField<SampleEnum> values = new RepeatedField<SampleEnum>();
values.AddEntriesFrom(input, FieldCodec.ForEnum(tag, x => (int)x, x => (SampleEnum)x));
Assert.AreEqual(6, values.Count);
Assert.AreEqual(SampleEnum.None, values[0]);
Assert.AreEqual(((SampleEnum)(-1)), values[1]);
Assert.AreEqual(SampleEnum.NegativeValue, values[2]);
Assert.AreEqual(((SampleEnum)(-3)), values[3]);
Assert.AreEqual(((SampleEnum)(-4)), values[4]);
Assert.AreEqual(((SampleEnum)(-5)), values[5]);
}
[Test]
public void TestNegativeEnumPackedArray()
{
int arraySize = 1 + (10 * 5);
int msgSize = 1 + 1 + arraySize;
byte[] bytes = new byte[msgSize];
CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
// Length-delimited to show we want the packed representation
uint tag = WireFormat.MakeTag(8, WireFormat.WireType.LengthDelimited);
output.WriteTag(tag);
int size = 0;
for (int i = 0; i >= -5; i--)
{
size += CodedOutputStream.ComputeEnumSize(i);
}
output.WriteRawVarint32((uint)size);
for (int i = 0; i >= -5; i--)
{
output.WriteEnum(i);
}
Assert.AreEqual(0, output.SpaceLeft);
CodedInputStream input = CodedInputStream.CreateInstance(bytes);
Assert.IsTrue(input.ReadTag(out tag));
RepeatedField<SampleEnum> values = new RepeatedField<SampleEnum>();
values.AddEntriesFrom(input, FieldCodec.ForEnum(tag, x => (int)x, x => (SampleEnum)x));
Assert.AreEqual(6, values.Count);
Assert.AreEqual(SampleEnum.None, values[0]);
Assert.AreEqual(((SampleEnum)(-1)), values[1]);
Assert.AreEqual(SampleEnum.NegativeValue, values[2]);
Assert.AreEqual(((SampleEnum)(-3)), values[3]);
Assert.AreEqual(((SampleEnum)(-4)), values[4]);
Assert.AreEqual(((SampleEnum)(-5)), values[5]);
}
}
}

@ -63,15 +63,21 @@ namespace Google.Protobuf
};
[Test, TestCaseSource("Codecs")]
public void RoundTrip(ICodecTestData codec)
public void RoundTripWithTag(ICodecTestData codec)
{
codec.TestRoundTrip();
codec.TestRoundTripWithTag();
}
[Test, TestCaseSource("Codecs")]
public void RoundTripRaw(ICodecTestData codec)
{
codec.TestRoundTripRaw();
}
[Test, TestCaseSource("Codecs")]
public void CalculateSize(ICodecTestData codec)
{
codec.TestCalculateSize();
codec.TestCalculateSizeWithTag();
}
[Test, TestCaseSource("Codecs")]
@ -82,8 +88,9 @@ namespace Google.Protobuf
public interface ICodecTestData
{
void TestRoundTrip();
void TestCalculateSize();
void TestRoundTripRaw();
void TestRoundTripWithTag();
void TestCalculateSizeWithTag();
void TestDefaultValue();
}
@ -100,45 +107,67 @@ namespace Google.Protobuf
this.name = name;
}
public void TestRoundTrip()
public void TestRoundTripRaw()
{
var stream = new MemoryStream();
var codedOutput = CodedOutputStream.CreateInstance(stream);
codec.Write(codedOutput, sampleValue);
codec.ValueWriter(codedOutput, sampleValue);
codedOutput.Flush();
stream.Position = 0;
var codedInput = CodedInputStream.CreateInstance(stream);
uint tag;
Assert.IsTrue(codedInput.ReadTag(out tag));
Assert.AreEqual(codec.Tag, tag);
Assert.AreEqual(sampleValue, codec.ValueReader(codedInput));
Assert.IsTrue(codedInput.IsAtEnd);
}
public void TestRoundTripWithTag()
{
var stream = new MemoryStream();
var codedOutput = CodedOutputStream.CreateInstance(stream);
codec.WriteTagAndValue(codedOutput, sampleValue);
codedOutput.Flush();
stream.Position = 0;
var codedInput = CodedInputStream.CreateInstance(stream);
codedInput.AssertNextTag(codec.Tag);
Assert.AreEqual(sampleValue, codec.Read(codedInput));
Assert.IsTrue(codedInput.IsAtEnd);
}
public void TestCalculateSize()
public void TestCalculateSizeWithTag()
{
var stream = new MemoryStream();
var codedOutput = CodedOutputStream.CreateInstance(stream);
codec.Write(codedOutput, sampleValue);
codec.WriteTagAndValue(codedOutput, sampleValue);
codedOutput.Flush();
Assert.AreEqual(stream.Position, codec.CalculateSize(sampleValue));
Assert.AreEqual(stream.Position, codec.CalculateSizeWithTag(sampleValue));
}
public void TestDefaultValue()
{
// WriteTagAndValue ignores default values
var stream = new MemoryStream();
var codedOutput = CodedOutputStream.CreateInstance(stream);
codec.Write(codedOutput, codec.DefaultValue);
codec.WriteTagAndValue(codedOutput, codec.DefaultValue);
codedOutput.Flush();
Assert.AreEqual(0, stream.Position);
Assert.AreEqual(0, codec.CalculateSize(codec.DefaultValue));
Assert.AreEqual(0, codec.CalculateSizeWithTag(codec.DefaultValue));
if (typeof(T).IsValueType)
{
Assert.AreEqual(default(T), codec.DefaultValue);
}
}
public string Description { get { return name; } }
// The plain ValueWriter/ValueReader delegates don't.
if (codec.DefaultValue != null) // This part isn't appropriate for message types.
{
codedOutput = CodedOutputStream.CreateInstance(stream);
codec.ValueWriter(codedOutput, codec.DefaultValue);
codedOutput.Flush();
Assert.AreNotEqual(0, stream.Position);
Assert.AreEqual(stream.Position, codec.ValueSizeCalculator(codec.DefaultValue));
stream.Position = 0;
var codedInput = CodedInputStream.CreateInstance(stream);
Assert.AreEqual(codec.DefaultValue, codec.ValueReader(codedInput));
}
}
public override string ToString()
{

@ -10,6 +10,61 @@ namespace Google.Protobuf
/// </summary>
public class GeneratedMessageTest
{
/// <summary>
/// Returns a sample TestAllTypes with all fields populated
/// </summary>
public static TestAllTypes GetSampleMessage()
{
return new TestAllTypes
{
SingleBool = true,
SingleBytes = ByteString.CopyFrom(1, 2, 3, 4),
SingleDouble = 23.5,
SingleFixed32 = 23,
SingleFixed64 = 1234567890123,
SingleFloat = 12.25f,
SingleForeignEnum = ForeignEnum.FOREIGN_BAR,
SingleForeignMessage = new ForeignMessage { C = 10 },
SingleImportEnum = ImportEnum.IMPORT_BAZ,
SingleImportMessage = new ImportMessage { D = 20 },
SingleInt32 = 100,
SingleInt64 = 3210987654321,
SingleNestedEnum = TestAllTypes.Types.NestedEnum.FOO,
SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 35 },
SinglePublicImportMessage = new PublicImportMessage { E = 54 },
SingleSfixed32 = -123,
SingleSfixed64 = -12345678901234,
SingleSint32 = -456,
SingleSint64 = -12345678901235,
SingleString = "test",
SingleUint32 = uint.MaxValue,
SingleUint64 = ulong.MaxValue,
RepeatedBool = { true, false },
RepeatedBytes = { ByteString.CopyFrom(1, 2, 3, 4), ByteString.CopyFrom(5, 6), ByteString.CopyFrom(new byte[1000]) },
RepeatedDouble = { -12.25, 23.5 },
RepeatedFixed32 = { uint.MaxValue, 23 },
RepeatedFixed64 = { ulong.MaxValue, 1234567890123 },
RepeatedFloat = { 100f, 12.25f },
RepeatedForeignEnum = { ForeignEnum.FOREIGN_FOO, ForeignEnum.FOREIGN_BAR },
RepeatedForeignMessage = { new ForeignMessage(), new ForeignMessage { C = 10 } },
RepeatedImportEnum = { ImportEnum.IMPORT_BAZ, ImportEnum.IMPORT_ENUM_UNSPECIFIED },
RepeatedImportMessage = { new ImportMessage { D = 20 }, new ImportMessage { D = 25 } },
RepeatedInt32 = { 100, 200 },
RepeatedInt64 = { 3210987654321, long.MaxValue },
RepeatedNestedEnum = { TestAllTypes.Types.NestedEnum.FOO, TestAllTypes.Types.NestedEnum.NEG },
RepeatedNestedMessage = { new TestAllTypes.Types.NestedMessage { Bb = 35 }, new TestAllTypes.Types.NestedMessage { Bb = 10 } },
RepeatedPublicImportMessage = { new PublicImportMessage { E = 54 }, new PublicImportMessage { E = -1 } },
RepeatedSfixed32 = { -123, 123 },
RepeatedSfixed64 = { -12345678901234, 12345678901234 },
RepeatedSint32 = { -456, 100 },
RepeatedSint64 = { -12345678901235, 123 },
RepeatedString = { "foo", "bar" },
RepeatedUint32 = { uint.MaxValue, uint.MinValue },
RepeatedUint64 = { ulong.MaxValue, uint.MinValue },
OneofString = "Oneof string"
};
}
[Test]
public void EmptyMessageFieldDistinctFromMissingMessageField()
{
@ -485,5 +540,83 @@ namespace Google.Protobuf
Assert.Throws<InvalidOperationException>(() => frozen.RepeatedDouble.Add(0.0));
Assert.Throws<InvalidOperationException>(() => frozen.RepeatedNestedMessage.Add(new TestAllTypes.Types.NestedMessage()));
}
[Test]
public void OneofProperties()
{
// Switch the oneof case between each of the different options, and check everything behaves
// as expected in each case.
var message = new TestAllTypes();
Assert.AreEqual("", message.OneofString);
Assert.AreEqual(0, message.OneofUint32);
Assert.AreEqual(ByteString.Empty, message.OneofBytes);
Assert.IsNull(message.OneofNestedMessage);
Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
message.OneofString = "sample";
Assert.AreEqual("sample", message.OneofString);
Assert.AreEqual(0, message.OneofUint32);
Assert.AreEqual(ByteString.Empty, message.OneofBytes);
Assert.IsNull(message.OneofNestedMessage);
Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofString, message.OneofFieldCase);
var bytes = ByteString.CopyFrom(1, 2, 3);
message.OneofBytes = bytes;
Assert.AreEqual("", message.OneofString);
Assert.AreEqual(0, message.OneofUint32);
Assert.AreEqual(bytes, message.OneofBytes);
Assert.IsNull(message.OneofNestedMessage);
Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofBytes, message.OneofFieldCase);
message.OneofUint32 = 20;
Assert.AreEqual("", message.OneofString);
Assert.AreEqual(20, message.OneofUint32);
Assert.AreEqual(ByteString.Empty, message.OneofBytes);
Assert.IsNull(message.OneofNestedMessage);
Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message.OneofFieldCase);
var nestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 25 };
message.OneofNestedMessage = nestedMessage;
Assert.AreEqual("", message.OneofString);
Assert.AreEqual(0, message.OneofUint32);
Assert.AreEqual(ByteString.Empty, message.OneofBytes);
Assert.AreEqual(nestedMessage, message.OneofNestedMessage);
Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofNestedMessage, message.OneofFieldCase);
message.ClearOneofField();
Assert.AreEqual("", message.OneofString);
Assert.AreEqual(0, message.OneofUint32);
Assert.AreEqual(ByteString.Empty, message.OneofBytes);
Assert.IsNull(message.OneofNestedMessage);
Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
}
[Test]
public void OneofSerialization_NonDefaultValue()
{
var message = new TestAllTypes();
message.OneofString = "this would take a bit of space";
message.OneofUint32 = 10;
var bytes = message.ToByteArray();
Assert.AreEqual(3, bytes.Length); // 2 bytes for the tag + 1 for the value - no string!
var message2 = TestAllTypes.Parser.ParseFrom(bytes);
Assert.AreEqual(message, message2);
Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message2.OneofFieldCase);
}
[Test]
public void OneofSerialization_DefaultValue()
{
var message = new TestAllTypes();
message.OneofString = "this would take a bit of space";
message.OneofUint32 = 0; // This is the default value for UInt32; normally wouldn't be serialized
var bytes = message.ToByteArray();
Assert.AreEqual(3, bytes.Length); // 2 bytes for the tag + 1 for the value - it's still serialized
var message2 = TestAllTypes.Parser.ParseFrom(bytes);
Assert.AreEqual(message, message2);
Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message2.OneofFieldCase);
}
}
}

@ -72,6 +72,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="ByteStringTest.cs" />
<Compile Include="CodedInputStreamExtensions.cs" />
<Compile Include="CodedInputStreamTest.cs" />
<Compile Include="CodedOutputStreamTest.cs" />
<Compile Include="EqualityTester.cs" />
@ -79,6 +80,7 @@
<Compile Include="GeneratedMessageTest.cs" />
<Compile Include="Collections\MapFieldTest.cs" />
<Compile Include="Collections\RepeatedFieldTest.cs" />
<Compile Include="SampleEnum.cs" />
<Compile Include="TestProtos\MapUnittestProto3.cs" />
<Compile Include="TestProtos\UnittestImportProto3.cs" />
<Compile Include="TestProtos\UnittestImportPublicProto3.cs" />

@ -0,0 +1,42 @@
#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
// Copyright 2015 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
namespace Google.Protobuf
{
// Just a sample enum with positive and negative values to be used in tests.
internal enum SampleEnum
{
NegativeValue = -2,
None = 0,
PositiveValue = 3
}
}

@ -422,13 +422,15 @@ namespace UnitTest.Issues.TestProtos {
}
public const int ValuesFieldNumber = 2;
private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> values_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum>();
private static readonly pb::FieldCodec<global::UnitTest.Issues.TestProtos.NegativeEnum> _repeated_values_codec
= pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::UnitTest.Issues.TestProtos.NegativeEnum) x);private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> values_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum>();
public pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> Values {
get { return values_; }
}
public const int PackedValuesFieldNumber = 3;
private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> packedValues_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum>();
private static readonly pb::FieldCodec<global::UnitTest.Issues.TestProtos.NegativeEnum> _repeated_packedValues_codec
= pb::FieldCodec.ForEnum(26, x => (int) x, x => (global::UnitTest.Issues.TestProtos.NegativeEnum) x);private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> packedValues_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum>();
public pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> PackedValues {
get { return packedValues_; }
}
@ -463,13 +465,8 @@ namespace UnitTest.Issues.TestProtos {
output.WriteRawTag(8);
output.WriteEnum((int) Value);
}
if (values_.Count > 0) {
output.WriteEnumArray(2, values_);
}
if (packedValues_.Count > 0) {
output.WriteRawTag(26);
output.WritePackedEnumArray(packedValues_);
}
values_.WriteTo(output, _repeated_values_codec);
packedValues_.WriteTo(output, _repeated_packedValues_codec);
}
public int CalculateSize() {
@ -477,22 +474,8 @@ namespace UnitTest.Issues.TestProtos {
if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO) {
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.ComputeEnumSize((int) element);
}
size += dataSize;
size += 1 * values_.Count;
}
if (packedValues_.Count > 0) {
int dataSize = 0;
foreach (global::UnitTest.Issues.TestProtos.NegativeEnum element in packedValues_) {
dataSize += pb::CodedOutputStream.ComputeEnumSize((int) element);
}
size += dataSize;
size += 1 + pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);
}
size += values_.CalculateSize(_repeated_values_codec);
size += packedValues_.CalculateSize(_repeated_packedValues_codec);
return size;
}
@ -524,12 +507,12 @@ namespace UnitTest.Issues.TestProtos {
}
case 18:
case 16: {
input.ReadEnumArray<global::UnitTest.Issues.TestProtos.NegativeEnum>(values_);
values_.AddEntriesFrom(input, _repeated_values_codec);
break;
}
case 26:
case 24: {
input.ReadEnumArray<global::UnitTest.Issues.TestProtos.NegativeEnum>(packedValues_);
packedValues_.AddEntriesFrom(input, _repeated_packedValues_codec);
break;
}
}
@ -678,6 +661,8 @@ namespace UnitTest.Issues.TestProtos {
}
public const int PrimitiveArrayFieldNumber = 2;
private static readonly pb::FieldCodec<int> _repeated_primitiveArray_codec
= pb::FieldCodec.ForInt32(18);
private readonly pbc::RepeatedField<int> primitiveArray_ = new pbc::RepeatedField<int>();
[global::System.ObsoleteAttribute()]
public pbc::RepeatedField<int> PrimitiveArray {
@ -696,6 +681,8 @@ namespace UnitTest.Issues.TestProtos {
}
public const int MessageArrayFieldNumber = 4;
private static readonly pb::FieldCodec<global::UnitTest.Issues.TestProtos.DeprecatedChild> _repeated_messageArray_codec
= pb::FieldCodec.ForMessage(34, global::UnitTest.Issues.TestProtos.DeprecatedChild.Parser);
private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedChild> messageArray_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedChild>();
[global::System.ObsoleteAttribute()]
public pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedChild> MessageArray {
@ -714,7 +701,8 @@ namespace UnitTest.Issues.TestProtos {
}
public const int EnumArrayFieldNumber = 6;
private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedEnum> enumArray_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedEnum>();
private static readonly pb::FieldCodec<global::UnitTest.Issues.TestProtos.DeprecatedEnum> _repeated_enumArray_codec
= pb::FieldCodec.ForEnum(50, x => (int) x, x => (global::UnitTest.Issues.TestProtos.DeprecatedEnum) x);private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedEnum> enumArray_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedEnum>();
[global::System.ObsoleteAttribute()]
public pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedEnum> EnumArray {
get { return enumArray_; }
@ -756,25 +744,17 @@ namespace UnitTest.Issues.TestProtos {
output.WriteRawTag(8);
output.WriteInt32(PrimitiveValue);
}
if (primitiveArray_.Count > 0) {
output.WriteRawTag(18);
output.WritePackedInt32Array(primitiveArray_);
}
primitiveArray_.WriteTo(output, _repeated_primitiveArray_codec);
if (messageValue_ != null) {
output.WriteRawTag(26);
output.WriteMessage(MessageValue);
}
if (messageArray_.Count > 0) {
output.WriteMessageArray(4, messageArray_);
}
messageArray_.WriteTo(output, _repeated_messageArray_codec);
if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO) {
output.WriteRawTag(40);
output.WriteEnum((int) EnumValue);
}
if (enumArray_.Count > 0) {
output.WriteRawTag(50);
output.WritePackedEnumArray(enumArray_);
}
enumArray_.WriteTo(output, _repeated_enumArray_codec);
}
public int CalculateSize() {
@ -782,34 +762,15 @@ namespace UnitTest.Issues.TestProtos {
if (PrimitiveValue != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(PrimitiveValue);
}
if (primitiveArray_.Count > 0) {
int dataSize = 0;
foreach (int element in primitiveArray_) {
dataSize += pb::CodedOutputStream.ComputeInt32Size(element);
}
size += dataSize;
size += 1 + pb::CodedOutputStream.ComputeInt32Size(dataSize);
}
size += primitiveArray_.CalculateSize(_repeated_primitiveArray_codec);
if (messageValue_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(MessageValue);
}
if (messageArray_.Count > 0) {
foreach (global::UnitTest.Issues.TestProtos.DeprecatedChild element in messageArray_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 1 * messageArray_.Count;
}
size += messageArray_.CalculateSize(_repeated_messageArray_codec);
if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO) {
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.ComputeEnumSize((int) element);
}
size += dataSize;
size += 1 + pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);
}
size += enumArray_.CalculateSize(_repeated_enumArray_codec);
return size;
}
@ -851,7 +812,7 @@ namespace UnitTest.Issues.TestProtos {
}
case 18:
case 16: {
input.ReadInt32Array(primitiveArray_);
primitiveArray_.AddEntriesFrom(input, _repeated_primitiveArray_codec);
break;
}
case 26: {
@ -862,7 +823,7 @@ namespace UnitTest.Issues.TestProtos {
break;
}
case 34: {
input.ReadMessageArray(messageArray_, global::UnitTest.Issues.TestProtos.DeprecatedChild.Parser);
messageArray_.AddEntriesFrom(input, _repeated_messageArray_codec);
break;
}
case 40: {
@ -871,7 +832,7 @@ namespace UnitTest.Issues.TestProtos {
}
case 50:
case 48: {
input.ReadEnumArray<global::UnitTest.Issues.TestProtos.DeprecatedEnum>(enumArray_);
enumArray_.AddEntriesFrom(input, _repeated_enumArray_codec);
break;
}
}

File diff suppressed because it is too large Load Diff

@ -37,7 +37,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using Google.Protobuf.Collections;
namespace Google.Protobuf
{
@ -172,8 +171,67 @@ namespace Google.Protobuf
}
}
#region Validation
/// <summary>
/// Returns the last tag read, or 0 if no tags have been read or we've read beyond
/// the end of the stream.
/// </summary>
internal uint LastTag { get { return lastTag; } }
#region Limits for recursion and length
/// <summary>
/// Set the maximum message recursion depth.
/// </summary>
/// <remarks>
/// In order to prevent malicious
/// messages from causing stack overflows, CodedInputStream limits
/// how deeply messages may be nested. The default limit is 64.
/// </remarks>
public int SetRecursionLimit(int limit)
{
if (limit < 0)
{
throw new ArgumentOutOfRangeException("Recursion limit cannot be negative: " + limit);
}
int oldLimit = recursionLimit;
recursionLimit = limit;
return oldLimit;
}
/// <summary>
/// Set the maximum message size.
/// </summary>
/// <remarks>
/// In order to prevent malicious messages from exhausting memory or
/// causing integer overflows, CodedInputStream limits how large a message may be.
/// The default limit is 64MB. You should set this limit as small
/// as you can without harming your app's functionality. Note that
/// size limits only apply when reading from an InputStream, not
/// when constructed around a raw byte array (nor with ByteString.NewCodedInput).
/// If you want to read several messages from a single CodedInputStream, you
/// can call ResetSizeCounter() after each message to avoid hitting the
/// size limit.
/// </remarks>
public int SetSizeLimit(int limit)
{
if (limit < 0)
{
throw new ArgumentOutOfRangeException("Size limit cannot be negative: " + limit);
}
int oldLimit = sizeLimit;
sizeLimit = limit;
return oldLimit;
}
/// <summary>
/// Resets the current size counter to zero (see <see cref="SetSizeLimit"/>).
/// </summary>
public void ResetSizeCounter()
{
totalBytesRetired = 0;
}
#endregion
#region Validation
/// <summary>
/// Verifies that the last call to ReadTag() returned the given tag value.
/// This is used to verify that a nested group ended with the correct
@ -188,13 +246,12 @@ namespace Google.Protobuf
throw InvalidProtocolBufferException.InvalidEndTag();
}
}
#endregion
#region Reading of tags etc
/// <summary>
/// Attempt to peek at the next field tag.
/// Attempts to peek at the next field tag.
/// </summary>
public bool PeekNextTag(out uint fieldTag)
{
@ -212,7 +269,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Attempt to read a field tag, returning false if we have reached the end
/// Attempts to read a field tag, returning false if we have reached the end
/// of the input data.
/// </summary>
/// <param name="fieldTag">The 'tag' of the field (id * 8 + wire-format)</param>
@ -227,14 +284,42 @@ namespace Google.Protobuf
return true;
}
if (IsAtEnd)
// Optimize for the incredibly common case of having at least two bytes left in the buffer,
// and those two bytes being enough to get the tag. This will be true for fields up to 4095.
if (bufferPos + 2 <= bufferSize)
{
fieldTag = 0;
lastTag = fieldTag;
return false;
int tmp = buffer[bufferPos++];
if (tmp < 128)
{
fieldTag = (uint)tmp;
}
else
{
int result = tmp & 0x7f;
if ((tmp = buffer[bufferPos++]) < 128)
{
result |= tmp << 7;
fieldTag = (uint) result;
}
else
{
// Nope, rewind and go the potentially slow route.
bufferPos -= 2;
fieldTag = ReadRawVarint32();
}
}
}
else
{
if (IsAtEnd)
{
fieldTag = 0;
lastTag = fieldTag;
return false;
}
fieldTag = ReadRawVarint32();
fieldTag = ReadRawVarint32();
}
lastTag = fieldTag;
if (lastTag == 0)
{
@ -245,7 +330,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Read a double field from the stream.
/// Reads a double field from the stream.
/// </summary>
public double ReadDouble()
{
@ -253,7 +338,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Read a float field from the stream.
/// Reads a float field from the stream.
/// </summary>
public float ReadFloat()
{
@ -275,7 +360,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Read a uint64 field from the stream.
/// Reads a uint64 field from the stream.
/// </summary>
public ulong ReadUInt64()
{
@ -283,7 +368,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Read an int64 field from the stream.
/// Reads an int64 field from the stream.
/// </summary>
public long ReadInt64()
{
@ -291,7 +376,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Read an int32 field from the stream.
/// Reads an int32 field from the stream.
/// </summary>
public int ReadInt32()
{
@ -299,7 +384,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Read a fixed64 field from the stream.
/// Reads a fixed64 field from the stream.
/// </summary>
public ulong ReadFixed64()
{
@ -307,7 +392,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Read a fixed32 field from the stream.
/// Reads a fixed32 field from the stream.
/// </summary>
public uint ReadFixed32()
{
@ -315,7 +400,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Read a bool field from the stream.
/// Reads a bool field from the stream.
/// </summary>
public bool ReadBool()
{
@ -327,22 +412,22 @@ namespace Google.Protobuf
/// </summary>
public string ReadString()
{
int size = (int) ReadRawVarint32();
int length = ReadLength();
// No need to read any data for an empty string.
if (size == 0)
if (length == 0)
{
return "";
}
if (size <= bufferSize - bufferPos)
if (length <= bufferSize - bufferPos)
{
// Fast path: We already have the bytes in a contiguous buffer, so
// just copy directly from it.
String result = CodedOutputStream.Utf8Encoding.GetString(buffer, bufferPos, size);
bufferPos += size;
String result = CodedOutputStream.Utf8Encoding.GetString(buffer, bufferPos, length);
bufferPos += length;
return result;
}
// Slow path: Build a byte array first then copy it.
return CodedOutputStream.Utf8Encoding.GetString(ReadRawBytes(size), 0, size);
return CodedOutputStream.Utf8Encoding.GetString(ReadRawBytes(length), 0, length);
}
/// <summary>
@ -350,7 +435,7 @@ namespace Google.Protobuf
/// </summary>
public void ReadMessage(IMessage builder)
{
int length = (int) ReadRawVarint32();
int length = ReadLength();
if (recursionDepth >= recursionLimit)
{
throw InvalidProtocolBufferException.RecursionLimitExceeded();
@ -368,19 +453,19 @@ namespace Google.Protobuf
/// </summary>
public ByteString ReadBytes()
{
int size = (int) ReadRawVarint32();
if (size <= bufferSize - bufferPos && size > 0)
int length = ReadLength();
if (length <= bufferSize - bufferPos && length > 0)
{
// Fast path: We already have the bytes in a contiguous buffer, so
// just copy directly from it.
ByteString result = ByteString.CopyFrom(buffer, bufferPos, size);
bufferPos += size;
ByteString result = ByteString.CopyFrom(buffer, bufferPos, length);
bufferPos += length;
return result;
}
else
{
// Slow path: Build a byte array and attach it to a new ByteString.
return ByteString.AttachBytes(ReadRawBytes(size));
return ByteString.AttachBytes(ReadRawBytes(length));
}
}
@ -435,24 +520,16 @@ namespace Google.Protobuf
return DecodeZigZag64(ReadRawVarint64());
}
private bool BeginArray(uint fieldTag, out bool isPacked, out int oldLimit)
/// <summary>
/// Reads a length for length-delimited data.
/// </summary>
/// <remarks>
/// This is internally just reading a varint, but this method exists
/// to make the calling code clearer.
/// </remarks>
public int ReadLength()
{
isPacked = WireFormat.GetTagWireType(fieldTag) == WireFormat.WireType.LengthDelimited;
if (isPacked)
{
int length = (int) (ReadRawVarint32() & int.MaxValue);
if (length > 0)
{
oldLimit = PushLimit(length);
return true;
}
oldLimit = -1;
return false; //packed but empty
}
oldLimit = -1;
return true;
return (int) ReadRawVarint32();
}
/// <summary>
@ -474,268 +551,6 @@ namespace Google.Protobuf
return false;
}
/// <summary>
/// Returns true if the next tag is also part of the same array, which may or may not be packed.
/// </summary>
private bool ContinueArray(uint currentTag, bool packed, int oldLimit)
{
if (packed)
{
if (ReachedLimit)
{
PopLimit(oldLimit);
return false;
}
return true;
}
return MaybeConsumeTag(currentTag);
}
/// <summary>
/// Reads a string array.
/// </summary>
/// <remarks>The stream is assumed to be positioned after a tag indicating the field
/// repeated string value. A string is read, and then if the next tag is the same,
/// the process is repeated, until the next tag is a different one.</remarks>
/// <param name="list"></param>
public void ReadStringArray(ICollection<string> list)
{
uint fieldTag = lastTag;
do
{
list.Add(ReadString());
} while (MaybeConsumeTag(fieldTag));
}
public void ReadBytesArray(ICollection<ByteString> list)
{
uint fieldTag = lastTag;
do
{
list.Add(ReadBytes());
} while (MaybeConsumeTag(fieldTag));
}
public void ReadBoolArray(ICollection<bool> list)
{
uint fieldTag = lastTag;
bool isPacked;
int holdLimit;
if (BeginArray(fieldTag, out isPacked, out holdLimit))
{
do
{
list.Add(ReadBool());
} while (ContinueArray(fieldTag, isPacked, holdLimit));
}
}
public void ReadInt32Array(ICollection<int> list)
{
uint fieldTag = lastTag;
bool isPacked;
int holdLimit;
if (BeginArray(fieldTag, out isPacked, out holdLimit))
{
do
{
list.Add(ReadInt32());
} while (ContinueArray(fieldTag, isPacked, holdLimit));
}
}
public void ReadSInt32Array(ICollection<int> list)
{
uint fieldTag = lastTag;
bool isPacked;
int holdLimit;
if (BeginArray(fieldTag, out isPacked, out holdLimit))
{
do
{
list.Add(ReadSInt32());
} while (ContinueArray(fieldTag, isPacked, holdLimit));
}
}
public void ReadUInt32Array(ICollection<uint> list)
{
uint fieldTag = lastTag;
bool isPacked;
int holdLimit;
if (BeginArray(fieldTag, out isPacked, out holdLimit))
{
do
{
list.Add(ReadUInt32());
} while (ContinueArray(fieldTag, isPacked, holdLimit));
}
}
public void ReadFixed32Array(ICollection<uint> list)
{
uint fieldTag = lastTag;
bool isPacked;
int holdLimit;
if (BeginArray(fieldTag, out isPacked, out holdLimit))
{
do
{
list.Add(ReadFixed32());
} while (ContinueArray(fieldTag, isPacked, holdLimit));
}
}
public void ReadSFixed32Array(ICollection<int> list)
{
uint fieldTag = lastTag;
bool isPacked;
int holdLimit;
if (BeginArray(fieldTag, out isPacked, out holdLimit))
{
do
{
list.Add(ReadSFixed32());
} while (ContinueArray(fieldTag, isPacked, holdLimit));
}
}
public void ReadInt64Array(ICollection<long> list)
{
uint fieldTag = lastTag;
bool isPacked;
int holdLimit;
if (BeginArray(fieldTag, out isPacked, out holdLimit))
{
do
{
list.Add(ReadInt64());
} while (ContinueArray(fieldTag, isPacked, holdLimit));
}
}
public void ReadSInt64Array(ICollection<long> list)
{
uint fieldTag = lastTag;
bool isPacked;
int holdLimit;
if (BeginArray(fieldTag, out isPacked, out holdLimit))
{
do
{
list.Add(ReadSInt64());
} while (ContinueArray(fieldTag, isPacked, holdLimit));
}
}
public void ReadUInt64Array(ICollection<ulong> list)
{
uint fieldTag = lastTag;
bool isPacked;
int holdLimit;
if (BeginArray(fieldTag, out isPacked, out holdLimit))
{
do
{
list.Add(ReadUInt64());
} while (ContinueArray(fieldTag, isPacked, holdLimit));
}
}
public void ReadFixed64Array(ICollection<ulong> list)
{
uint fieldTag = lastTag;
bool isPacked;
int holdLimit;
if (BeginArray(fieldTag, out isPacked, out holdLimit))
{
do
{
list.Add(ReadFixed64());
} while (ContinueArray(fieldTag, isPacked, holdLimit));
}
}
public void ReadSFixed64Array(ICollection<long> list)
{
uint fieldTag = lastTag;
bool isPacked;
int holdLimit;
if (BeginArray(fieldTag, out isPacked, out holdLimit))
{
do
{
list.Add(ReadSFixed64());
} while (ContinueArray(fieldTag, isPacked, holdLimit));
}
}
public void ReadDoubleArray(ICollection<double> list)
{
uint fieldTag = lastTag;
bool isPacked;
int holdLimit;
if (BeginArray(fieldTag, out isPacked, out holdLimit))
{
do
{
list.Add(ReadDouble());
} while (ContinueArray(fieldTag, isPacked, holdLimit));
}
}
public void ReadFloatArray(ICollection<float> list)
{
uint fieldTag = lastTag;
bool isPacked;
int holdLimit;
if (BeginArray(fieldTag, out isPacked, out holdLimit))
{
do
{
list.Add(ReadFloat());
} while (ContinueArray(fieldTag, isPacked, holdLimit));
}
}
public void ReadEnumArray<T>(RepeatedField<T> list)
where T : struct, IComparable, IFormattable
{
uint fieldTag = lastTag;
WireFormat.WireType wformat = WireFormat.GetTagWireType(fieldTag);
// 2.3 allows packed form even if the field is not declared packed.
if (wformat == WireFormat.WireType.LengthDelimited)
{
int length = (int) (ReadRawVarint32() & int.MaxValue);
int limit = PushLimit(length);
while (!ReachedLimit)
{
// Ghastly hack, but it works...
list.AddInt32(ReadEnum());
}
PopLimit(limit);
}
else
{
do
{
list.Add((T)(object) ReadEnum());
} while (MaybeConsumeTag(fieldTag));
}
}
public void ReadMessageArray<T>(ICollection<T> list, MessageParser<T> messageParser)
where T : IMessage<T>
{
uint fieldTag = lastTag;
do
{
T message = messageParser.CreateTemplate();
ReadMessage(message);
list.Add(message);
} while (MaybeConsumeTag(fieldTag));
}
#endregion
#region Underlying reading primitives
@ -793,12 +608,12 @@ namespace Google.Protobuf
}
/// <summary>
/// Read a raw Varint from the stream. If larger than 32 bits, discard the upper bits.
/// Reads a raw Varint from the stream. If larger than 32 bits, discard the upper bits.
/// This method is optimised for the case where we've got lots of data in the buffer.
/// That means we can check the size just once, then just read directly from the buffer
/// without constant rechecking of the buffer length.
/// </summary>
public uint ReadRawVarint32()
internal uint ReadRawVarint32()
{
if (bufferPos + 5 > bufferSize)
{
@ -857,13 +672,13 @@ namespace Google.Protobuf
/// <summary>
/// Reads a varint from the input one byte at a time, so that it does not
/// read any bytes after the end of the varint. If you simply wrapped the
/// stream in a CodedInputStream and used ReadRawVarint32(Stream)}
/// stream in a CodedInputStream and used ReadRawVarint32(Stream)
/// then you would probably end up reading past the end of the varint since
/// CodedInputStream buffers its input.
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public static uint ReadRawVarint32(Stream input)
internal static uint ReadRawVarint32(Stream input)
{
int result = 0;
int offset = 0;
@ -897,9 +712,9 @@ namespace Google.Protobuf
}
/// <summary>
/// Read a raw varint from the stream.
/// Reads a raw varint from the stream.
/// </summary>
public ulong ReadRawVarint64()
internal ulong ReadRawVarint64()
{
int shift = 0;
ulong result = 0;
@ -917,9 +732,9 @@ namespace Google.Protobuf
}
/// <summary>
/// Read a 32-bit little-endian integer from the stream.
/// Reads a 32-bit little-endian integer from the stream.
/// </summary>
public uint ReadRawLittleEndian32()
internal uint ReadRawLittleEndian32()
{
uint b1 = ReadRawByte();
uint b2 = ReadRawByte();
@ -929,9 +744,9 @@ namespace Google.Protobuf
}
/// <summary>
/// Read a 64-bit little-endian integer from the stream.
/// Reads a 64-bit little-endian integer from the stream.
/// </summary>
public ulong ReadRawLittleEndian64()
internal ulong ReadRawLittleEndian64()
{
ulong b1 = ReadRawByte();
ulong b2 = ReadRawByte();
@ -945,8 +760,6 @@ namespace Google.Protobuf
| (b5 << 32) | (b6 << 40) | (b7 << 48) | (b8 << 56);
}
#endregion
/// <summary>
/// Decode a 32-bit value with ZigZag encoding.
/// </summary>
@ -956,9 +769,9 @@ namespace Google.Protobuf
/// sign-extended to 64 bits to be varint encoded, thus always taking
/// 10 bytes on the wire.)
/// </remarks>
public static int DecodeZigZag32(uint n)
internal static int DecodeZigZag32(uint n)
{
return (int) (n >> 1) ^ -(int) (n & 1);
return (int)(n >> 1) ^ -(int)(n & 1);
}
/// <summary>
@ -970,72 +783,21 @@ namespace Google.Protobuf
/// sign-extended to 64 bits to be varint encoded, thus always taking
/// 10 bytes on the wire.)
/// </remarks>
public static long DecodeZigZag64(ulong n)
internal static long DecodeZigZag64(ulong n)
{
return (long) (n >> 1) ^ -(long) (n & 1);
}
/// <summary>
/// Set the maximum message recursion depth.
/// </summary>
/// <remarks>
/// In order to prevent malicious
/// messages from causing stack overflows, CodedInputStream limits
/// how deeply messages may be nested. The default limit is 64.
/// </remarks>
public int SetRecursionLimit(int limit)
{
if (limit < 0)
{
throw new ArgumentOutOfRangeException("Recursion limit cannot be negative: " + limit);
}
int oldLimit = recursionLimit;
recursionLimit = limit;
return oldLimit;
}
/// <summary>
/// Set the maximum message size.
/// </summary>
/// <remarks>
/// In order to prevent malicious messages from exhausting memory or
/// causing integer overflows, CodedInputStream limits how large a message may be.
/// The default limit is 64MB. You should set this limit as small
/// as you can without harming your app's functionality. Note that
/// size limits only apply when reading from an InputStream, not
/// when constructed around a raw byte array (nor with ByteString.NewCodedInput).
/// If you want to read several messages from a single CodedInputStream, you
/// can call ResetSizeCounter() after each message to avoid hitting the
/// size limit.
/// </remarks>
public int SetSizeLimit(int limit)
{
if (limit < 0)
{
throw new ArgumentOutOfRangeException("Size limit cannot be negative: " + limit);
}
int oldLimit = sizeLimit;
sizeLimit = limit;
return oldLimit;
return (long)(n >> 1) ^ -(long)(n & 1);
}
#endregion
#region Internal reading and buffer management
/// <summary>
/// Resets the current size counter to zero (see SetSizeLimit).
/// </summary>
public void ResetSizeCounter()
{
totalBytesRetired = 0;
}
/// <summary>
/// Sets currentLimit to (current position) + byteLimit. This is called
/// when descending into a length-delimited embedded message. The previous
/// limit is returned.
/// </summary>
/// <returns>The old limit.</returns>
public int PushLimit(int byteLimit)
internal int PushLimit(int byteLimit)
{
if (byteLimit < 0)
{
@ -1073,7 +835,7 @@ namespace Google.Protobuf
/// <summary>
/// Discards the current limit, returning the previous limit.
/// </summary>
public void PopLimit(int oldLimit)
internal void PopLimit(int oldLimit)
{
currentLimit = oldLimit;
RecomputeBufferSizeAfterLimit();
@ -1083,7 +845,7 @@ namespace Google.Protobuf
/// Returns whether or not all the data before the limit has been read.
/// </summary>
/// <returns></returns>
public bool ReachedLimit
internal bool ReachedLimit
{
get
{
@ -1173,7 +935,7 @@ namespace Google.Protobuf
/// <exception cref="InvalidProtocolBufferException">
/// the end of the stream or the current limit was reached
/// </exception>
public byte ReadRawByte()
internal byte ReadRawByte()
{
if (bufferPos == bufferSize)
{
@ -1183,12 +945,12 @@ namespace Google.Protobuf
}
/// <summary>
/// Read a fixed size of bytes from the input.
/// Reads a fixed size of bytes from the input.
/// </summary>
/// <exception cref="InvalidProtocolBufferException">
/// the end of the stream or the current limit was reached
/// </exception>
public byte[] ReadRawBytes(int size)
internal byte[] ReadRawBytes(int size)
{
if (size < 0)
{
@ -1197,7 +959,8 @@ namespace Google.Protobuf
if (totalBytesRetired + bufferPos + size > currentLimit)
{
// Read to the end of the stream anyway.
// Read to the end of the stream (up to the current limit) anyway.
// TODO(jonskeet): This is the only usage of SkipRawBytes. Do we really need to do it?
SkipRawBytes(currentLimit - totalBytesRetired - bufferPos);
// Then fail.
throw InvalidProtocolBufferException.TruncatedMessage();
@ -1301,63 +1064,12 @@ namespace Google.Protobuf
}
}
/// <summary>
/// Reads and discards a single field, given its tag value.
/// </summary>
/// <returns>false if the tag is an end-group tag, in which case
/// nothing is skipped. Otherwise, returns true.</returns>
public bool SkipField()
{
uint tag = lastTag;
switch (WireFormat.GetTagWireType(tag))
{
case WireFormat.WireType.Varint:
ReadRawVarint64();
return true;
case WireFormat.WireType.Fixed64:
ReadRawLittleEndian64();
return true;
case WireFormat.WireType.LengthDelimited:
SkipRawBytes((int) ReadRawVarint32());
return true;
case WireFormat.WireType.StartGroup:
SkipMessage();
CheckLastTagWas(
WireFormat.MakeTag(WireFormat.GetTagFieldNumber(tag),
WireFormat.WireType.EndGroup));
return true;
case WireFormat.WireType.EndGroup:
return false;
case WireFormat.WireType.Fixed32:
ReadRawLittleEndian32();
return true;
default:
throw InvalidProtocolBufferException.InvalidWireType();
}
}
/// <summary>
/// Reads and discards an entire message. This will read either until EOF
/// or until an endgroup tag, whichever comes first.
/// </summary>
public void SkipMessage()
{
uint tag;
while (ReadTag(out tag))
{
if (!SkipField())
{
return;
}
}
}
/// <summary>
/// Reads and discards <paramref name="size"/> bytes.
/// </summary>
/// <exception cref="InvalidProtocolBufferException">the end of the stream
/// or the current limit was reached</exception>
public void SkipRawBytes(int size)
private void SkipRawBytes(int size)
{
if (size < 0)
{

@ -50,7 +50,7 @@ namespace Google.Protobuf
private const int LittleEndian32Size = 4;
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// Computes the number of bytes that would be needed to encode a
/// double field, including the tag.
/// </summary>
public static int ComputeDoubleSize(double value)
@ -59,7 +59,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// Computes the number of bytes that would be needed to encode a
/// float field, including the tag.
/// </summary>
public static int ComputeFloatSize(float value)
@ -68,7 +68,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// Computes the number of bytes that would be needed to encode a
/// uint64 field, including the tag.
/// </summary>
public static int ComputeUInt64Size(ulong value)
@ -77,7 +77,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Compute the number of bytes that would be needed to encode an
/// Computes the number of bytes that would be needed to encode an
/// int64 field, including the tag.
/// </summary>
public static int ComputeInt64Size(long value)
@ -86,7 +86,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Compute the number of bytes that would be needed to encode an
/// Computes the number of bytes that would be needed to encode an
/// int32 field, including the tag.
/// </summary>
public static int ComputeInt32Size(int value)
@ -103,7 +103,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// Computes the number of bytes that would be needed to encode a
/// fixed64 field, including the tag.
/// </summary>
public static int ComputeFixed64Size(ulong value)
@ -112,7 +112,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// Computes the number of bytes that would be needed to encode a
/// fixed32 field, including the tag.
/// </summary>
public static int ComputeFixed32Size(uint value)
@ -121,7 +121,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// Computes the number of bytes that would be needed to encode a
/// bool field, including the tag.
/// </summary>
public static int ComputeBoolSize(bool value)
@ -130,7 +130,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// Computes the number of bytes that would be needed to encode a
/// string field, including the tag.
/// </summary>
public static int ComputeStringSize(String value)
@ -141,7 +141,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// Computes the number of bytes that would be needed to encode a
/// group field, including the tag.
/// </summary>
public static int ComputeGroupSize(IMessage value)
@ -150,7 +150,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Compute the number of bytes that would be needed to encode an
/// Computes the number of bytes that would be needed to encode an
/// embedded message field, including the tag.
/// </summary>
public static int ComputeMessageSize(IMessage value)
@ -160,7 +160,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// Computes the number of bytes that would be needed to encode a
/// bytes field, including the tag.
/// </summary>
public static int ComputeBytesSize(ByteString value)
@ -170,7 +170,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// Computes the number of bytes that would be needed to encode a
/// uint32 field, including the tag.
/// </summary>
public static int ComputeUInt32Size(uint value)
@ -179,7 +179,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// Computes 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>
@ -190,7 +190,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Compute the number of bytes that would be needed to encode an
/// Computes the number of bytes that would be needed to encode an
/// sfixed32 field, including the tag.
/// </summary>
public static int ComputeSFixed32Size(int value)
@ -199,7 +199,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Compute the number of bytes that would be needed to encode an
/// Computes the number of bytes that would be needed to encode an
/// sfixed64 field, including the tag.
/// </summary>
public static int ComputeSFixed64Size(long value)
@ -208,7 +208,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Compute the number of bytes that would be needed to encode an
/// Computes the number of bytes that would be needed to encode an
/// sint32 field, including the tag.
/// </summary>
public static int ComputeSInt32Size(int value)
@ -217,7 +217,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Compute the number of bytes that would be needed to encode an
/// Computes the number of bytes that would be needed to encode an
/// sint64 field, including the tag.
/// </summary>
public static int ComputeSInt64Size(long value)
@ -226,7 +226,16 @@ namespace Google.Protobuf
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a varint.
/// Computes the number of bytes that would be needed to encode a length,
/// as written by <see cref="WriteLength"/>.
/// </summary>
public static int ComputeLengthSize(int length)
{
return ComputeRawVarint32Size((uint) length);
}
/// <summary>
/// Computes the number of bytes that would be needed to encode a varint.
/// </summary>
public static int ComputeRawVarint32Size(uint value)
{
@ -250,7 +259,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a varint.
/// Computes the number of bytes that would be needed to encode a varint.
/// </summary>
public static int ComputeRawVarint64Size(ulong value)
{
@ -294,7 +303,7 @@ namespace Google.Protobuf
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a tag.
/// Computes the number of bytes that would be needed to encode a tag.
/// </summary>
public static int ComputeTagSize(int fieldNumber)
{

@ -37,7 +37,6 @@
using System;
using System.IO;
using System.Text;
using Google.Protobuf.Collections;
namespace Google.Protobuf
{
@ -141,11 +140,12 @@ namespace Google.Protobuf
}
}
#region Writing of values without tags
#region Writing of values (not including tags)
/// <summary>
/// Writes a double field value, including tag, to the stream.
/// Writes a double field value, without a tag, to the stream.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteDouble(double value)
{
WriteRawLittleEndian64((ulong)BitConverter.DoubleToInt64Bits(value));
@ -154,6 +154,7 @@ namespace Google.Protobuf
/// <summary>
/// Writes a float field value, without a tag, to the stream.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteFloat(float value)
{
byte[] rawBytes = BitConverter.GetBytes(value);
@ -178,6 +179,7 @@ namespace Google.Protobuf
/// <summary>
/// Writes a uint64 field value, without a tag, to the stream.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteUInt64(ulong value)
{
WriteRawVarint64(value);
@ -186,6 +188,7 @@ namespace Google.Protobuf
/// <summary>
/// Writes an int64 field value, without a tag, to the stream.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteInt64(long value)
{
WriteRawVarint64((ulong) value);
@ -194,6 +197,7 @@ namespace Google.Protobuf
/// <summary>
/// Writes an int32 field value, without a tag, to the stream.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteInt32(int value)
{
if (value >= 0)
@ -210,6 +214,7 @@ namespace Google.Protobuf
/// <summary>
/// Writes a fixed64 field value, without a tag, to the stream.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteFixed64(ulong value)
{
WriteRawLittleEndian64(value);
@ -218,6 +223,7 @@ namespace Google.Protobuf
/// <summary>
/// Writes a fixed32 field value, without a tag, to the stream.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteFixed32(uint value)
{
WriteRawLittleEndian32(value);
@ -226,6 +232,7 @@ namespace Google.Protobuf
/// <summary>
/// Writes a bool field value, without a tag, to the stream.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteBool(bool value)
{
WriteRawByte(value ? (byte) 1 : (byte) 0);
@ -233,13 +240,15 @@ namespace Google.Protobuf
/// <summary>
/// Writes a string field value, without a tag, to the stream.
/// The data is length-prefixed.
/// </summary>
/// <param name="value">The value to write</param>
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 = Utf8Encoding.GetByteCount(value);
WriteRawVarint32((uint)length);
WriteLength(length);
if (limit - position >= length)
{
if (length == value.Length) // Must be all ASCII...
@ -262,23 +271,41 @@ namespace Google.Protobuf
}
}
/// <summary>
/// Writes a message, without a tag, to the stream.
/// The data is length-prefixed.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteMessage(IMessage value)
{
WriteRawVarint32((uint) value.CalculateSize());
value.WriteTo(this);
}
/// <summary>
/// Write a byte string, without a tag, to the stream.
/// The data is length-prefixed.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteBytes(ByteString value)
{
WriteRawVarint32((uint) value.Length);
value.WriteRawBytesTo(this);
}
/// <summary>
/// Writes a uint32 value, without a tag, to the stream.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteUInt32(uint value)
{
WriteRawVarint32(value);
}
/// <summary>
/// Writes an enum value, without a tag, to the stream.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteEnum(int value)
{
WriteInt32(value);
@ -289,179 +316,43 @@ namespace Google.Protobuf
WriteRawLittleEndian32((uint) value);
}
/// <summary>
/// Writes an sfixed64 value, without a tag, to the stream.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteSFixed64(long value)
{
WriteRawLittleEndian64((ulong) value);
}
/// <summary>
/// Writes an sint32 value, without a tag, to the stream.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteSInt32(int value)
{
WriteRawVarint32(EncodeZigZag32(value));
}
/// <summary>
/// Writes an sint64 value, without a tag, to the stream.
/// </summary>
/// <param name="value">The value to write</param>
public void WriteSInt64(long value)
{
WriteRawVarint64(EncodeZigZag64(value));
}
#endregion
#region Write array members, with fields.
public void WriteMessageArray<T>(int fieldNumber, RepeatedField<T> list)
where T : IMessage
{
foreach (T value in list)
{
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
WriteMessage(value);
}
}
public void WriteStringArray(int fieldNumber, RepeatedField<string> list)
{
foreach (var value in list)
{
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
WriteString(value);
}
}
public void WriteBytesArray(int fieldNumber, RepeatedField<ByteString> list)
{
foreach (var value in list)
{
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
WriteBytes(value);
}
}
public void WriteBoolArray(int fieldNumber, RepeatedField<bool> list)
{
foreach (var value in list)
{
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteBool(value);
}
}
public void WriteInt32Array(int fieldNumber, RepeatedField<int> list)
{
foreach (var value in list)
{
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteInt32(value);
}
}
public void WriteSInt32Array(int fieldNumber, RepeatedField<int> list)
{
foreach (var value in list)
{
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteSInt32(value);
}
}
public void WriteUInt32Array(int fieldNumber, RepeatedField<uint> list)
{
foreach (var value in list)
{
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteUInt32(value);
}
}
public void WriteFixed32Array(int fieldNumber, RepeatedField<uint> list)
{
foreach (var value in list)
{
WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
WriteFixed32(value);
}
}
public void WriteSFixed32Array(int fieldNumber, RepeatedField<int> list)
{
foreach (var value in list)
{
WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
WriteSFixed32(value);
}
}
public void WriteInt64Array(int fieldNumber, RepeatedField<long> list)
{
foreach (var value in list)
{
WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
WriteInt64(value);
}
}
public void WriteSInt64Array(int fieldNumber, RepeatedField<long> list)
{
foreach (var value in list)
{
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteSInt64(value);
}
}
public void WriteUInt64Array(int fieldNumber, RepeatedField<ulong> list)
{
foreach (var value in list)
{
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteUInt64(value);
}
}
public void WriteFixed64Array(int fieldNumber, RepeatedField<ulong> list)
{
foreach (var value in list)
{
WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
WriteFixed64(value);
}
}
public void WriteSFixed64Array(int fieldNumber, RepeatedField<long> list)
{
foreach (var value in list)
{
WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
WriteSFixed64(value);
}
}
public void WriteDoubleArray(int fieldNumber, RepeatedField<double> list)
{
foreach (var value in list)
{
WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
WriteDouble(value);
}
}
public void WriteFloatArray(int fieldNumber, RepeatedField<float> list)
{
foreach (var value in list)
{
WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
WriteFloat(value);
}
}
public void WriteEnumArray<T>(int fieldNumber, RepeatedField<T> list)
where T : struct, IComparable, IFormattable
/// <summary>
/// Writes a length (in bytes) for length-delimited data.
/// </summary>
/// <remarks>
/// This method simply writes a rawint, but exists for clarity in calling code.
/// </remarks>
/// <param name="length">Length value, in bytes.</param>
public void WriteLength(int length)
{
// Bit of a hack, to access the values as ints
var iterator = list.GetInt32Enumerator();
while (iterator.MoveNext())
{
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteEnum(iterator.Current);
}
WriteRawVarint32((uint) length);
}
#endregion
@ -470,6 +361,8 @@ namespace Google.Protobuf
/// <summary>
/// Encodes and writes a tag.
/// </summary>
/// <param name="fieldNumber">The number of the field to write the tag for</param>
/// <param name="type">The wire format type of the tag to write</param>
public void WriteTag(int fieldNumber, WireFormat.WireType type)
{
WriteRawVarint32(WireFormat.MakeTag(fieldNumber, type));
@ -478,6 +371,7 @@ namespace Google.Protobuf
/// <summary>
/// Writes an already-encoded tag.
/// </summary>
/// <param name="tag">The encoded tag</param>
public void WriteTag(uint tag)
{
WriteRawVarint32(tag);
@ -486,6 +380,7 @@ namespace Google.Protobuf
/// <summary>
/// Writes the given single-byte tag directly to the stream.
/// </summary>
/// <param name="b1">The encoded tag</param>
public void WriteRawTag(byte b1)
{
WriteRawByte(b1);
@ -494,6 +389,8 @@ namespace Google.Protobuf
/// <summary>
/// Writes the given two-byte tag directly to the stream.
/// </summary>
/// <param name="b1">The first byte of the encoded tag</param>
/// <param name="b2">The second byte of the encoded tag</param>
public void WriteRawTag(byte b1, byte b2)
{
WriteRawByte(b1);
@ -503,6 +400,9 @@ namespace Google.Protobuf
/// <summary>
/// Writes the given three-byte tag directly to the stream.
/// </summary>
/// <param name="b1">The first byte of the encoded tag</param>
/// <param name="b2">The second byte of the encoded tag</param>
/// <param name="b3">The third byte of the encoded tag</param>
public void WriteRawTag(byte b1, byte b2, byte b3)
{
WriteRawByte(b1);
@ -513,6 +413,10 @@ namespace Google.Protobuf
/// <summary>
/// Writes the given four-byte tag directly to the stream.
/// </summary>
/// <param name="b1">The first byte of the encoded tag</param>
/// <param name="b2">The second byte of the encoded tag</param>
/// <param name="b3">The third byte of the encoded tag</param>
/// <param name="b4">The fourth byte of the encoded tag</param>
public void WriteRawTag(byte b1, byte b2, byte b3, byte b4)
{
WriteRawByte(b1);
@ -524,6 +428,11 @@ namespace Google.Protobuf
/// <summary>
/// Writes the given five-byte tag directly to the stream.
/// </summary>
/// <param name="b1">The first byte of the encoded tag</param>
/// <param name="b2">The second byte of the encoded tag</param>
/// <param name="b3">The third byte of the encoded tag</param>
/// <param name="b4">The fourth byte of the encoded tag</param>
/// <param name="b5">The fifth byte of the encoded tag</param>
public void WriteRawTag(byte b1, byte b2, byte b3, byte b4, byte b5)
{
WriteRawByte(b1);
@ -534,178 +443,13 @@ namespace Google.Protobuf
}
#endregion
#region Write packed array members
// TODO(jonskeet): A lot of these are really inefficient, due to method group conversions. Fix!
// (Alternatively, add extension methods to RepeatedField, accepting the Write* methods via delegates too.)
public void WritePackedBoolArray(RepeatedField<bool> list)
{
uint size = (uint)list.Count;
WriteRawVarint32(size);
foreach (var value in list)
{
WriteBool(value);
}
}
public void WritePackedInt32Array(RepeatedField<int> list)
{
uint size = list.CalculateSize(ComputeInt32Size);
WriteRawVarint32(size);
foreach (var value in list)
{
WriteInt32(value);
}
}
public void WritePackedSInt32Array(RepeatedField<int> list)
{
uint size = list.CalculateSize(ComputeSInt32Size);
WriteRawVarint32(size);
foreach (var value in list)
{
WriteSInt32(value);
}
}
public void WritePackedUInt32Array(RepeatedField<uint> list)
{
uint size = list.CalculateSize(ComputeUInt32Size);
WriteRawVarint32(size);
foreach (var value in list)
{
WriteUInt32(value);
}
}
public void WritePackedFixed32Array(RepeatedField<uint> list)
{
uint size = (uint) list.Count * 4;
WriteRawVarint32(size);
foreach (var value in list)
{
WriteFixed32(value);
}
}
public void WritePackedSFixed32Array(RepeatedField<int> list)
{
uint size = (uint) list.Count * 4;
WriteRawVarint32(size);
foreach (var value in list)
{
WriteSFixed32(value);
}
}
public void WritePackedInt64Array(RepeatedField<long> list)
{
uint size = list.CalculateSize(ComputeInt64Size);
WriteRawVarint32(size);
foreach (var value in list)
{
WriteInt64(value);
}
}
public void WritePackedSInt64Array(RepeatedField<long> list)
{
uint size = list.CalculateSize(ComputeSInt64Size);
WriteRawVarint32(size);
foreach (var value in list)
{
WriteSInt64(value);
}
}
public void WritePackedUInt64Array(RepeatedField<ulong> list)
{
if (list.Count == 0)
{
return;
}
uint size = list.CalculateSize(ComputeUInt64Size);
WriteRawVarint32(size);
foreach (var value in list)
{
WriteUInt64(value);
}
}
public void WritePackedFixed64Array(RepeatedField<ulong> list)
{
uint size = (uint) list.Count * 8;
WriteRawVarint32(size);
foreach (var value in list)
{
WriteFixed64(value);
}
}
public void WritePackedSFixed64Array(RepeatedField<long> list)
{
uint size = (uint) list.Count * 8;
WriteRawVarint32(size);
foreach (var value in list)
{
WriteSFixed64(value);
}
}
public void WritePackedDoubleArray(RepeatedField<double> list)
{
uint size = (uint) list.Count * 8;
WriteRawVarint32(size);
foreach (var value in list)
{
WriteDouble(value);
}
}
public void WritePackedFloatArray(RepeatedField<float> list)
{
if (list.Count == 0)
{
return;
}
uint size = (uint) list.Count * 4;
WriteRawVarint32(size);
foreach (var value in list)
{
WriteFloat(value);
}
}
public void WritePackedEnumArray<T>(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();
uint size = 0;
while (iterator.MoveNext())
{
size += (uint) ComputeEnumSize(iterator.Current);
}
iterator.Reset();
WriteRawVarint32(size);
while (iterator.MoveNext())
{
WriteEnum(iterator.Current);
}
}
#endregion
#region Underlying writing primitives
/// <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
/// for each byte; otherwise, we resort to calling WriteRawByte each time.
/// </summary>
public void WriteRawVarint32(uint value)
internal void WriteRawVarint32(uint value)
{
// Optimize for the common case of a single byte value
if (value < 128 && position < limit)
@ -734,7 +478,7 @@ namespace Google.Protobuf
}
}
public void WriteRawVarint64(ulong value)
internal void WriteRawVarint64(ulong value)
{
while (value > 127 && position < limit)
{
@ -756,7 +500,7 @@ namespace Google.Protobuf
}
}
public void WriteRawLittleEndian32(uint value)
internal void WriteRawLittleEndian32(uint value)
{
if (position + 4 > limit)
{
@ -774,7 +518,7 @@ namespace Google.Protobuf
}
}
public void WriteRawLittleEndian64(ulong value)
internal void WriteRawLittleEndian64(ulong value)
{
if (position + 8 > limit)
{
@ -800,7 +544,7 @@ namespace Google.Protobuf
}
}
public void WriteRawByte(byte value)
internal void WriteRawByte(byte value)
{
if (position == limit)
{
@ -810,7 +554,7 @@ namespace Google.Protobuf
buffer[position++] = value;
}
public void WriteRawByte(uint value)
internal void WriteRawByte(uint value)
{
WriteRawByte((byte) value);
}
@ -818,7 +562,7 @@ namespace Google.Protobuf
/// <summary>
/// Writes out an array of bytes.
/// </summary>
public void WriteRawBytes(byte[] value)
internal void WriteRawBytes(byte[] value)
{
WriteRawBytes(value, 0, value.Length);
}
@ -826,7 +570,7 @@ namespace Google.Protobuf
/// <summary>
/// Writes out part of an array of bytes.
/// </summary>
public void WriteRawBytes(byte[] value, int offset, int length)
internal void WriteRawBytes(byte[] value, int offset, int length)
{
if (limit - position >= length)
{
@ -873,7 +617,7 @@ namespace Google.Protobuf
/// sign-extended to 64 bits to be varint encoded, thus always taking
/// 10 bytes on the wire.)
/// </remarks>
public static uint EncodeZigZag32(int n)
internal static uint EncodeZigZag32(int n)
{
// Note: the right-shift must be arithmetic
return (uint) ((n << 1) ^ (n >> 31));
@ -888,7 +632,7 @@ namespace Google.Protobuf
/// sign-extended to 64 bits to be varint encoded, thus always taking
/// 10 bytes on the wire.)
/// </remarks>
public static ulong EncodeZigZag64(long n)
internal static ulong EncodeZigZag64(long n)
{
return (ulong) ((n << 1) ^ (n >> 63));
}

@ -334,6 +334,10 @@ namespace Google.Protobuf.Collections
public int CalculateSize(Codec codec)
{
if (Count == 0)
{
return 0;
}
var message = new Codec.MessageAdapter(codec);
int size = 0;
foreach (var entry in list)
@ -419,13 +423,13 @@ namespace Google.Protobuf.Collections
public void WriteTo(CodedOutputStream output)
{
codec.keyCodec.Write(output, Key);
codec.valueCodec.Write(output, Value);
codec.keyCodec.WriteTagAndValue(output, Key);
codec.valueCodec.WriteTagAndValue(output, Value);
}
public int CalculateSize()
{
return codec.keyCodec.CalculateSize(Key) + codec.valueCodec.CalculateSize(Value);
return codec.keyCodec.CalculateSizeWithTag(Key) + codec.valueCodec.CalculateSizeWithTag(Value);
}
}
}

@ -38,7 +38,7 @@ namespace Google.Protobuf.Collections
/// <summary>
/// Read-only wrapper around another dictionary.
/// </summary>
public sealed class ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey, TValue>
internal sealed class ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
private readonly IDictionary<TKey, TValue> wrapped;

@ -49,6 +49,113 @@ namespace Google.Protobuf.Collections
return clone;
}
public void AddEntriesFrom(CodedInputStream input, FieldCodec<T> codec)
{
// TODO: Inline some of the Add code, so we can avoid checking the size on every
// iteration and the mutability.
uint tag = input.LastTag;
var reader = codec.ValueReader;
// Value types can be packed or not.
if (typeof(T).IsValueType && WireFormat.GetTagWireType(tag) == WireFormat.WireType.LengthDelimited)
{
int length = input.ReadLength();
if (length > 0)
{
int oldLimit = input.PushLimit(length);
while (!input.ReachedLimit)
{
Add(reader(input));
}
input.PopLimit(oldLimit);
}
// Empty packed field. Odd, but valid - just ignore.
}
else
{
// Not packed... (possibly not packable)
do
{
Add(reader(input));
} while (input.MaybeConsumeTag(tag));
}
}
public int CalculateSize(FieldCodec<T> codec)
{
if (count == 0)
{
return 0;
}
uint tag = codec.Tag;
if (typeof(T).IsValueType && WireFormat.GetTagWireType(tag) == WireFormat.WireType.LengthDelimited)
{
int dataSize = CalculatePackedDataSize(codec);
return CodedOutputStream.ComputeRawVarint32Size(tag) +
CodedOutputStream.ComputeRawVarint32Size((uint)dataSize) +
dataSize;
}
else
{
var sizeCalculator = codec.ValueSizeCalculator;
int size = count * CodedOutputStream.ComputeRawVarint32Size(tag);
for (int i = 0; i < count; i++)
{
size += sizeCalculator(array[i]);
}
return size;
}
}
private int CalculatePackedDataSize(FieldCodec<T> codec)
{
int fixedSize = codec.FixedSize;
if (fixedSize == 0)
{
var calculator = codec.ValueSizeCalculator;
int tmp = 0;
for (int i = 0; i < count; i++)
{
tmp += calculator(array[i]);
}
return tmp;
}
else
{
return fixedSize * Count;
}
}
public void WriteTo(CodedOutputStream output, FieldCodec<T> codec)
{
if (count == 0)
{
return;
}
var writer = codec.ValueWriter;
var tag = codec.Tag;
if (typeof(T).IsValueType && WireFormat.GetTagWireType(tag) == WireFormat.WireType.LengthDelimited)
{
// Packed primitive type
uint size = (uint)CalculatePackedDataSize(codec);
output.WriteTag(tag);
output.WriteRawVarint32(size);
for (int i = 0; i < count; i++)
{
writer(output, array[i]);
}
}
else
{
// Not packed: a simple tag/value pair for each value.
// Can't use codec.WriteTagAndValue, as that omits default values.
for (int i = 0; i < count; i++)
{
output.WriteTag(tag);
writer(output, array[i]);
}
}
}
public bool IsFrozen { get { return frozen; } }
public void Freeze()
@ -66,9 +173,9 @@ namespace Google.Protobuf.Collections
private void EnsureSize(int size)
{
size = Math.Max(size, MinArraySize);
if (array.Length < size)
{
size = Math.Max(size, MinArraySize);
int newSize = Math.Max(array.Length * 2, size);
var tmp = new T[newSize];
Array.Copy(array, 0, tmp, 0, array.Length);
@ -87,18 +194,6 @@ namespace Google.Protobuf.Collections
array[count++] = item;
}
/// <summary>
/// Hack to allow us to add enums easily... will only work with int-based types.
/// </summary>
/// <param name="readEnum"></param>
internal void AddInt32(int item)
{
this.CheckMutable();
EnsureSize(count + 1);
int[] castArray = (int[]) (object) array;
castArray[count++] = item;
}
public void Clear()
{
this.CheckMutable();
@ -180,16 +275,7 @@ namespace Google.Protobuf.Collections
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
/// <summary>
/// Returns an enumerator of the values in this list as integers.
/// Used for enum types.
/// </summary>
internal Int32Enumerator GetInt32Enumerator()
{
return new Int32Enumerator((int[])(object)array, count);
}
}
public override int GetHashCode()
{
@ -297,17 +383,7 @@ namespace Google.Protobuf.Collections
array[index] = value;
}
}
internal uint CalculateSize(Func<T, int> sizeComputer)
{
int size = 0;
for (int i = 0; i < count; i++)
{
size += sizeComputer(array[i]);
}
return (uint)size;
}
public struct Enumerator : IEnumerator<T>
{
private int index;
@ -355,46 +431,5 @@ namespace Google.Protobuf.Collections
{
}
}
internal struct Int32Enumerator : IEnumerator<int>
{
private int index;
private readonly int[] array;
private readonly int count;
public Int32Enumerator(int[] array, int count)
{
this.array = array;
this.index = -1;
this.count = count;
}
public bool MoveNext()
{
if (index + 1 >= count)
{
return false;
}
index++;
return true;
}
public void Reset()
{
index = -1;
}
// No guard here, as we're only going to use this internally...
public int Current { get { return array[index]; } }
object IEnumerator.Current
{
get { return Current; }
}
public void Dispose()
{
}
}
}
}

@ -314,6 +314,8 @@ namespace Google.Protobuf.DescriptorProtos {
}
public const int FileFieldNumber = 1;
private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.FileDescriptorProto> _repeated_file_codec
= pb::FieldCodec.ForMessage(10, global::Google.Protobuf.DescriptorProtos.FileDescriptorProto.Parser);
private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FileDescriptorProto> file_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FileDescriptorProto>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FileDescriptorProto> File {
get { return file_; }
@ -341,19 +343,12 @@ namespace Google.Protobuf.DescriptorProtos {
}
public void WriteTo(pb::CodedOutputStream output) {
if (file_.Count > 0) {
output.WriteMessageArray(1, file_);
}
file_.WriteTo(output, _repeated_file_codec);
}
public int CalculateSize() {
int size = 0;
if (file_.Count > 0) {
foreach (global::Google.Protobuf.DescriptorProtos.FileDescriptorProto element in file_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 1 * file_.Count;
}
size += file_.CalculateSize(_repeated_file_codec);
return size;
}
@ -376,7 +371,7 @@ namespace Google.Protobuf.DescriptorProtos {
}
break;
case 10: {
input.ReadMessageArray(file_, global::Google.Protobuf.DescriptorProtos.FileDescriptorProto.Parser);
file_.AddEntriesFrom(input, _repeated_file_codec);
break;
}
}
@ -461,42 +456,56 @@ namespace Google.Protobuf.DescriptorProtos {
}
public const int DependencyFieldNumber = 3;
private static readonly pb::FieldCodec<string> _repeated_dependency_codec
= pb::FieldCodec.ForString(26);
private readonly pbc::RepeatedField<string> dependency_ = new pbc::RepeatedField<string>();
public pbc::RepeatedField<string> Dependency {
get { return dependency_; }
}
public const int PublicDependencyFieldNumber = 10;
private static readonly pb::FieldCodec<int> _repeated_publicDependency_codec
= pb::FieldCodec.ForInt32(80);
private readonly pbc::RepeatedField<int> publicDependency_ = new pbc::RepeatedField<int>();
public pbc::RepeatedField<int> PublicDependency {
get { return publicDependency_; }
}
public const int WeakDependencyFieldNumber = 11;
private static readonly pb::FieldCodec<int> _repeated_weakDependency_codec
= pb::FieldCodec.ForInt32(88);
private readonly pbc::RepeatedField<int> weakDependency_ = new pbc::RepeatedField<int>();
public pbc::RepeatedField<int> WeakDependency {
get { return weakDependency_; }
}
public const int MessageTypeFieldNumber = 4;
private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.DescriptorProto> _repeated_messageType_codec
= pb::FieldCodec.ForMessage(34, global::Google.Protobuf.DescriptorProtos.DescriptorProto.Parser);
private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto> messageType_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto> MessageType {
get { return messageType_; }
}
public const int EnumTypeFieldNumber = 5;
private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto> _repeated_enumType_codec
= pb::FieldCodec.ForMessage(42, global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto.Parser);
private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto> enumType_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto> EnumType {
get { return enumType_; }
}
public const int ServiceFieldNumber = 6;
private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.ServiceDescriptorProto> _repeated_service_codec
= pb::FieldCodec.ForMessage(50, global::Google.Protobuf.DescriptorProtos.ServiceDescriptorProto.Parser);
private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.ServiceDescriptorProto> service_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.ServiceDescriptorProto>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.ServiceDescriptorProto> Service {
get { return service_; }
}
public const int ExtensionFieldNumber = 7;
private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto> _repeated_extension_codec
= pb::FieldCodec.ForMessage(58, global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Parser);
private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto> extension_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto> Extension {
get { return extension_; }
@ -584,21 +593,11 @@ namespace Google.Protobuf.DescriptorProtos {
output.WriteRawTag(18);
output.WriteString(Package);
}
if (dependency_.Count > 0) {
output.WriteStringArray(3, dependency_);
}
if (messageType_.Count > 0) {
output.WriteMessageArray(4, messageType_);
}
if (enumType_.Count > 0) {
output.WriteMessageArray(5, enumType_);
}
if (service_.Count > 0) {
output.WriteMessageArray(6, service_);
}
if (extension_.Count > 0) {
output.WriteMessageArray(7, extension_);
}
dependency_.WriteTo(output, _repeated_dependency_codec);
messageType_.WriteTo(output, _repeated_messageType_codec);
enumType_.WriteTo(output, _repeated_enumType_codec);
service_.WriteTo(output, _repeated_service_codec);
extension_.WriteTo(output, _repeated_extension_codec);
if (options_ != null) {
output.WriteRawTag(66);
output.WriteMessage(Options);
@ -607,12 +606,8 @@ namespace Google.Protobuf.DescriptorProtos {
output.WriteRawTag(74);
output.WriteMessage(SourceCodeInfo);
}
if (publicDependency_.Count > 0) {
output.WriteInt32Array(10, publicDependency_);
}
if (weakDependency_.Count > 0) {
output.WriteInt32Array(11, weakDependency_);
}
publicDependency_.WriteTo(output, _repeated_publicDependency_codec);
weakDependency_.WriteTo(output, _repeated_weakDependency_codec);
if (Syntax.Length != 0) {
output.WriteRawTag(98);
output.WriteString(Syntax);
@ -627,54 +622,13 @@ namespace Google.Protobuf.DescriptorProtos {
if (Package.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Package);
}
if (dependency_.Count > 0) {
int dataSize = 0;
foreach (string element in dependency_) {
dataSize += pb::CodedOutputStream.ComputeStringSize(element);
}
size += dataSize;
size += 1 * dependency_.Count;
}
if (publicDependency_.Count > 0) {
int dataSize = 0;
foreach (int element in publicDependency_) {
dataSize += pb::CodedOutputStream.ComputeInt32Size(element);
}
size += dataSize;
size += 1 * publicDependency_.Count;
}
if (weakDependency_.Count > 0) {
int dataSize = 0;
foreach (int element in weakDependency_) {
dataSize += pb::CodedOutputStream.ComputeInt32Size(element);
}
size += dataSize;
size += 1 * weakDependency_.Count;
}
if (messageType_.Count > 0) {
foreach (global::Google.Protobuf.DescriptorProtos.DescriptorProto element in messageType_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 1 * messageType_.Count;
}
if (enumType_.Count > 0) {
foreach (global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto element in enumType_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 1 * enumType_.Count;
}
if (service_.Count > 0) {
foreach (global::Google.Protobuf.DescriptorProtos.ServiceDescriptorProto element in service_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 1 * service_.Count;
}
if (extension_.Count > 0) {
foreach (global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto element in extension_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 1 * extension_.Count;
}
size += dependency_.CalculateSize(_repeated_dependency_codec);
size += publicDependency_.CalculateSize(_repeated_publicDependency_codec);
size += weakDependency_.CalculateSize(_repeated_weakDependency_codec);
size += messageType_.CalculateSize(_repeated_messageType_codec);
size += enumType_.CalculateSize(_repeated_enumType_codec);
size += service_.CalculateSize(_repeated_service_codec);
size += extension_.CalculateSize(_repeated_extension_codec);
if (options_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
}
@ -741,23 +695,23 @@ namespace Google.Protobuf.DescriptorProtos {
break;
}
case 26: {
input.ReadStringArray(dependency_);
dependency_.AddEntriesFrom(input, _repeated_dependency_codec);
break;
}
case 34: {
input.ReadMessageArray(messageType_, global::Google.Protobuf.DescriptorProtos.DescriptorProto.Parser);
messageType_.AddEntriesFrom(input, _repeated_messageType_codec);
break;
}
case 42: {
input.ReadMessageArray(enumType_, global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto.Parser);
enumType_.AddEntriesFrom(input, _repeated_enumType_codec);
break;
}
case 50: {
input.ReadMessageArray(service_, global::Google.Protobuf.DescriptorProtos.ServiceDescriptorProto.Parser);
service_.AddEntriesFrom(input, _repeated_service_codec);
break;
}
case 58: {
input.ReadMessageArray(extension_, global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Parser);
extension_.AddEntriesFrom(input, _repeated_extension_codec);
break;
}
case 66: {
@ -776,12 +730,12 @@ namespace Google.Protobuf.DescriptorProtos {
}
case 82:
case 80: {
input.ReadInt32Array(publicDependency_);
publicDependency_.AddEntriesFrom(input, _repeated_publicDependency_codec);
break;
}
case 90:
case 88: {
input.ReadInt32Array(weakDependency_);
weakDependency_.AddEntriesFrom(input, _repeated_weakDependency_codec);
break;
}
case 98: {
@ -858,36 +812,48 @@ namespace Google.Protobuf.DescriptorProtos {
}
public const int FieldFieldNumber = 2;
private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto> _repeated_field_codec
= pb::FieldCodec.ForMessage(18, global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Parser);
private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto> field_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto> Field {
get { return field_; }
}
public const int ExtensionFieldNumber = 6;
private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto> _repeated_extension_codec
= pb::FieldCodec.ForMessage(50, global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Parser);
private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto> extension_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto> Extension {
get { return extension_; }
}
public const int NestedTypeFieldNumber = 3;
private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.DescriptorProto> _repeated_nestedType_codec
= pb::FieldCodec.ForMessage(26, global::Google.Protobuf.DescriptorProtos.DescriptorProto.Parser);
private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto> nestedType_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto> NestedType {
get { return nestedType_; }
}
public const int EnumTypeFieldNumber = 4;
private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto> _repeated_enumType_codec
= pb::FieldCodec.ForMessage(34, global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto.Parser);
private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto> enumType_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto> EnumType {
get { return enumType_; }
}
public const int ExtensionRangeFieldNumber = 5;
private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ExtensionRange> _repeated_extensionRange_codec
= pb::FieldCodec.ForMessage(42, global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ExtensionRange.Parser);
private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ExtensionRange> extensionRange_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ExtensionRange>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ExtensionRange> ExtensionRange {
get { return extensionRange_; }
}
public const int OneofDeclFieldNumber = 8;
private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.OneofDescriptorProto> _repeated_oneofDecl_codec
= pb::FieldCodec.ForMessage(66, global::Google.Protobuf.DescriptorProtos.OneofDescriptorProto.Parser);
private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.OneofDescriptorProto> oneofDecl_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.OneofDescriptorProto>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.OneofDescriptorProto> OneofDecl {
get { return oneofDecl_; }
@ -904,12 +870,16 @@ namespace Google.Protobuf.DescriptorProtos {
}
public const int ReservedRangeFieldNumber = 9;
private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ReservedRange> _repeated_reservedRange_codec
= pb::FieldCodec.ForMessage(74, global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ReservedRange.Parser);
private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ReservedRange> reservedRange_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ReservedRange>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ReservedRange> ReservedRange {
get { return reservedRange_; }
}
public const int ReservedNameFieldNumber = 10;
private static readonly pb::FieldCodec<string> _repeated_reservedName_codec
= pb::FieldCodec.ForString(82);
private readonly pbc::RepeatedField<string> reservedName_ = new pbc::RepeatedField<string>();
public pbc::RepeatedField<string> ReservedName {
get { return reservedName_; }
@ -959,34 +929,18 @@ namespace Google.Protobuf.DescriptorProtos {
output.WriteRawTag(10);
output.WriteString(Name);
}
if (field_.Count > 0) {
output.WriteMessageArray(2, field_);
}
if (nestedType_.Count > 0) {
output.WriteMessageArray(3, nestedType_);
}
if (enumType_.Count > 0) {
output.WriteMessageArray(4, enumType_);
}
if (extensionRange_.Count > 0) {
output.WriteMessageArray(5, extensionRange_);
}
if (extension_.Count > 0) {
output.WriteMessageArray(6, extension_);
}
field_.WriteTo(output, _repeated_field_codec);
nestedType_.WriteTo(output, _repeated_nestedType_codec);
enumType_.WriteTo(output, _repeated_enumType_codec);
extensionRange_.WriteTo(output, _repeated_extensionRange_codec);
extension_.WriteTo(output, _repeated_extension_codec);
if (options_ != null) {
output.WriteRawTag(58);
output.WriteMessage(Options);
}
if (oneofDecl_.Count > 0) {
output.WriteMessageArray(8, oneofDecl_);
}
if (reservedRange_.Count > 0) {
output.WriteMessageArray(9, reservedRange_);
}
if (reservedName_.Count > 0) {
output.WriteStringArray(10, reservedName_);
}
oneofDecl_.WriteTo(output, _repeated_oneofDecl_codec);
reservedRange_.WriteTo(output, _repeated_reservedRange_codec);
reservedName_.WriteTo(output, _repeated_reservedName_codec);
}
public int CalculateSize() {
@ -994,59 +948,17 @@ namespace Google.Protobuf.DescriptorProtos {
if (Name.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
}
if (field_.Count > 0) {
foreach (global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto element in field_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 1 * field_.Count;
}
if (extension_.Count > 0) {
foreach (global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto element in extension_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 1 * extension_.Count;
}
if (nestedType_.Count > 0) {
foreach (global::Google.Protobuf.DescriptorProtos.DescriptorProto element in nestedType_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 1 * nestedType_.Count;
}
if (enumType_.Count > 0) {
foreach (global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto element in enumType_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 1 * enumType_.Count;
}
if (extensionRange_.Count > 0) {
foreach (global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ExtensionRange element in extensionRange_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 1 * extensionRange_.Count;
}
if (oneofDecl_.Count > 0) {
foreach (global::Google.Protobuf.DescriptorProtos.OneofDescriptorProto element in oneofDecl_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 1 * oneofDecl_.Count;
}
size += field_.CalculateSize(_repeated_field_codec);
size += extension_.CalculateSize(_repeated_extension_codec);
size += nestedType_.CalculateSize(_repeated_nestedType_codec);
size += enumType_.CalculateSize(_repeated_enumType_codec);
size += extensionRange_.CalculateSize(_repeated_extensionRange_codec);
size += oneofDecl_.CalculateSize(_repeated_oneofDecl_codec);
if (options_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
}
if (reservedRange_.Count > 0) {
foreach (global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ReservedRange element in reservedRange_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 1 * reservedRange_.Count;
}
if (reservedName_.Count > 0) {
int dataSize = 0;
foreach (string element in reservedName_) {
dataSize += pb::CodedOutputStream.ComputeStringSize(element);
}
size += dataSize;
size += 1 * reservedName_.Count;
}
size += reservedRange_.CalculateSize(_repeated_reservedRange_codec);
size += reservedName_.CalculateSize(_repeated_reservedName_codec);
return size;
}
@ -1089,23 +1001,23 @@ namespace Google.Protobuf.DescriptorProtos {
break;
}
case 18: {
input.ReadMessageArray(field_, global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Parser);
field_.AddEntriesFrom(input, _repeated_field_codec);
break;
}
case 26: {
input.ReadMessageArray(nestedType_, global::Google.Protobuf.DescriptorProtos.DescriptorProto.Parser);
nestedType_.AddEntriesFrom(input, _repeated_nestedType_codec);
break;
}
case 34: {
input.ReadMessageArray(enumType_, global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto.Parser);
enumType_.AddEntriesFrom(input, _repeated_enumType_codec);
break;
}
case 42: {
input.ReadMessageArray(extensionRange_, global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ExtensionRange.Parser);
extensionRange_.AddEntriesFrom(input, _repeated_extensionRange_codec);
break;
}
case 50: {
input.ReadMessageArray(extension_, global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Parser);
extension_.AddEntriesFrom(input, _repeated_extension_codec);
break;
}
case 58: {
@ -1116,15 +1028,15 @@ namespace Google.Protobuf.DescriptorProtos {
break;
}
case 66: {
input.ReadMessageArray(oneofDecl_, global::Google.Protobuf.DescriptorProtos.OneofDescriptorProto.Parser);
oneofDecl_.AddEntriesFrom(input, _repeated_oneofDecl_codec);
break;
}
case 74: {
input.ReadMessageArray(reservedRange_, global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ReservedRange.Parser);
reservedRange_.AddEntriesFrom(input, _repeated_reservedRange_codec);
break;
}
case 82: {
input.ReadStringArray(reservedName_);
reservedName_.AddEntriesFrom(input, _repeated_reservedName_codec);
break;
}
}
@ -1943,6 +1855,8 @@ namespace Google.Protobuf.DescriptorProtos {
}
public const int ValueFieldNumber = 2;
private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.EnumValueDescriptorProto> _repeated_value_codec
= pb::FieldCodec.ForMessage(18, global::Google.Protobuf.DescriptorProtos.EnumValueDescriptorProto.Parser);
private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.EnumValueDescriptorProto> value_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.EnumValueDescriptorProto>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.EnumValueDescriptorProto> Value {
get { return value_; }
@ -1988,9 +1902,7 @@ namespace Google.Protobuf.DescriptorProtos {
output.WriteRawTag(10);
output.WriteString(Name);
}
if (value_.Count > 0) {
output.WriteMessageArray(2, value_);
}
value_.WriteTo(output, _repeated_value_codec);
if (options_ != null) {
output.WriteRawTag(26);
output.WriteMessage(Options);
@ -2002,12 +1914,7 @@ namespace Google.Protobuf.DescriptorProtos {
if (Name.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
}
if (value_.Count > 0) {
foreach (global::Google.Protobuf.DescriptorProtos.EnumValueDescriptorProto element in value_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 1 * value_.Count;
}
size += value_.CalculateSize(_repeated_value_codec);
if (options_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
}
@ -2046,7 +1953,7 @@ namespace Google.Protobuf.DescriptorProtos {
break;
}
case 18: {
input.ReadMessageArray(value_, global::Google.Protobuf.DescriptorProtos.EnumValueDescriptorProto.Parser);
value_.AddEntriesFrom(input, _repeated_value_codec);
break;
}
case 26: {
@ -2284,6 +2191,8 @@ namespace Google.Protobuf.DescriptorProtos {
}
public const int MethodFieldNumber = 2;
private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.MethodDescriptorProto> _repeated_method_codec
= pb::FieldCodec.ForMessage(18, global::Google.Protobuf.DescriptorProtos.MethodDescriptorProto.Parser);
private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.MethodDescriptorProto> method_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.MethodDescriptorProto>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.MethodDescriptorProto> Method {
get { return method_; }
@ -2329,9 +2238,7 @@ namespace Google.Protobuf.DescriptorProtos {
output.WriteRawTag(10);
output.WriteString(Name);
}
if (method_.Count > 0) {
output.WriteMessageArray(2, method_);
}
method_.WriteTo(output, _repeated_method_codec);
if (options_ != null) {
output.WriteRawTag(26);
output.WriteMessage(Options);
@ -2343,12 +2250,7 @@ namespace Google.Protobuf.DescriptorProtos {
if (Name.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
}
if (method_.Count > 0) {
foreach (global::Google.Protobuf.DescriptorProtos.MethodDescriptorProto element in method_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 1 * method_.Count;
}
size += method_.CalculateSize(_repeated_method_codec);
if (options_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
}
@ -2387,7 +2289,7 @@ namespace Google.Protobuf.DescriptorProtos {
break;
}
case 18: {
input.ReadMessageArray(method_, global::Google.Protobuf.DescriptorProtos.MethodDescriptorProto.Parser);
method_.AddEntriesFrom(input, _repeated_method_codec);
break;
}
case 26: {
@ -2847,6 +2749,8 @@ namespace Google.Protobuf.DescriptorProtos {
}
public const int UninterpretedOptionFieldNumber = 999;
private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> _repeated_uninterpretedOption_codec
= pb::FieldCodec.ForMessage(7994, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser);
private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> UninterpretedOption {
get { return uninterpretedOption_; }
@ -2958,9 +2862,7 @@ namespace Google.Protobuf.DescriptorProtos {
output.WriteRawTag(170, 2);
output.WriteString(CsharpNamespace);
}
if (uninterpretedOption_.Count > 0) {
output.WriteMessageArray(999, uninterpretedOption_);
}
uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec);
}
public int CalculateSize() {
@ -3007,12 +2909,7 @@ namespace Google.Protobuf.DescriptorProtos {
if (CsharpNamespace.Length != 0) {
size += 2 + pb::CodedOutputStream.ComputeStringSize(CsharpNamespace);
}
if (uninterpretedOption_.Count > 0) {
foreach (global::Google.Protobuf.DescriptorProtos.UninterpretedOption element in uninterpretedOption_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 2 * uninterpretedOption_.Count;
}
size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec);
return size;
}
@ -3133,7 +3030,7 @@ namespace Google.Protobuf.DescriptorProtos {
break;
}
case 7994: {
input.ReadMessageArray(uninterpretedOption_, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser);
uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec);
break;
}
}
@ -3235,6 +3132,8 @@ namespace Google.Protobuf.DescriptorProtos {
}
public const int UninterpretedOptionFieldNumber = 999;
private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> _repeated_uninterpretedOption_codec
= pb::FieldCodec.ForMessage(7994, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser);
private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> UninterpretedOption {
get { return uninterpretedOption_; }
@ -3286,9 +3185,7 @@ namespace Google.Protobuf.DescriptorProtos {
output.WriteRawTag(56);
output.WriteBool(MapEntry);
}
if (uninterpretedOption_.Count > 0) {
output.WriteMessageArray(999, uninterpretedOption_);
}
uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec);
}
public int CalculateSize() {
@ -3305,12 +3202,7 @@ namespace Google.Protobuf.DescriptorProtos {
if (MapEntry != false) {
size += 1 + 1;
}
if (uninterpretedOption_.Count > 0) {
foreach (global::Google.Protobuf.DescriptorProtos.UninterpretedOption element in uninterpretedOption_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 2 * uninterpretedOption_.Count;
}
size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec);
return size;
}
@ -3361,7 +3253,7 @@ namespace Google.Protobuf.DescriptorProtos {
break;
}
case 7994: {
input.ReadMessageArray(uninterpretedOption_, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser);
uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec);
break;
}
}
@ -3473,6 +3365,8 @@ namespace Google.Protobuf.DescriptorProtos {
}
public const int UninterpretedOptionFieldNumber = 999;
private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> _repeated_uninterpretedOption_codec
= pb::FieldCodec.ForMessage(7994, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser);
private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> UninterpretedOption {
get { return uninterpretedOption_; }
@ -3536,9 +3430,7 @@ namespace Google.Protobuf.DescriptorProtos {
output.WriteRawTag(80);
output.WriteBool(Weak);
}
if (uninterpretedOption_.Count > 0) {
output.WriteMessageArray(999, uninterpretedOption_);
}
uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec);
}
public int CalculateSize() {
@ -3561,12 +3453,7 @@ namespace Google.Protobuf.DescriptorProtos {
if (Weak != false) {
size += 1 + 1;
}
if (uninterpretedOption_.Count > 0) {
foreach (global::Google.Protobuf.DescriptorProtos.UninterpretedOption element in uninterpretedOption_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 2 * uninterpretedOption_.Count;
}
size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec);
return size;
}
@ -3631,7 +3518,7 @@ namespace Google.Protobuf.DescriptorProtos {
break;
}
case 7994: {
input.ReadMessageArray(uninterpretedOption_, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser);
uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec);
break;
}
}
@ -3717,6 +3604,8 @@ namespace Google.Protobuf.DescriptorProtos {
}
public const int UninterpretedOptionFieldNumber = 999;
private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> _repeated_uninterpretedOption_codec
= pb::FieldCodec.ForMessage(7994, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser);
private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> UninterpretedOption {
get { return uninterpretedOption_; }
@ -3756,9 +3645,7 @@ namespace Google.Protobuf.DescriptorProtos {
output.WriteRawTag(24);
output.WriteBool(Deprecated);
}
if (uninterpretedOption_.Count > 0) {
output.WriteMessageArray(999, uninterpretedOption_);
}
uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec);
}
public int CalculateSize() {
@ -3769,12 +3656,7 @@ namespace Google.Protobuf.DescriptorProtos {
if (Deprecated != false) {
size += 1 + 1;
}
if (uninterpretedOption_.Count > 0) {
foreach (global::Google.Protobuf.DescriptorProtos.UninterpretedOption element in uninterpretedOption_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 2 * uninterpretedOption_.Count;
}
size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec);
return size;
}
@ -3811,7 +3693,7 @@ namespace Google.Protobuf.DescriptorProtos {
break;
}
case 7994: {
input.ReadMessageArray(uninterpretedOption_, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser);
uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec);
break;
}
}
@ -3868,6 +3750,8 @@ namespace Google.Protobuf.DescriptorProtos {
}
public const int UninterpretedOptionFieldNumber = 999;
private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> _repeated_uninterpretedOption_codec
= pb::FieldCodec.ForMessage(7994, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser);
private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> UninterpretedOption {
get { return uninterpretedOption_; }
@ -3901,9 +3785,7 @@ namespace Google.Protobuf.DescriptorProtos {
output.WriteRawTag(8);
output.WriteBool(Deprecated);
}
if (uninterpretedOption_.Count > 0) {
output.WriteMessageArray(999, uninterpretedOption_);
}
uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec);
}
public int CalculateSize() {
@ -3911,12 +3793,7 @@ namespace Google.Protobuf.DescriptorProtos {
if (Deprecated != false) {
size += 1 + 1;
}
if (uninterpretedOption_.Count > 0) {
foreach (global::Google.Protobuf.DescriptorProtos.UninterpretedOption element in uninterpretedOption_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 2 * uninterpretedOption_.Count;
}
size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec);
return size;
}
@ -3946,7 +3823,7 @@ namespace Google.Protobuf.DescriptorProtos {
break;
}
case 7994: {
input.ReadMessageArray(uninterpretedOption_, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser);
uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec);
break;
}
}
@ -4003,6 +3880,8 @@ namespace Google.Protobuf.DescriptorProtos {
}
public const int UninterpretedOptionFieldNumber = 999;
private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> _repeated_uninterpretedOption_codec
= pb::FieldCodec.ForMessage(7994, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser);
private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> UninterpretedOption {
get { return uninterpretedOption_; }
@ -4036,9 +3915,7 @@ namespace Google.Protobuf.DescriptorProtos {
output.WriteRawTag(136, 2);
output.WriteBool(Deprecated);
}
if (uninterpretedOption_.Count > 0) {
output.WriteMessageArray(999, uninterpretedOption_);
}
uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec);
}
public int CalculateSize() {
@ -4046,12 +3923,7 @@ namespace Google.Protobuf.DescriptorProtos {
if (Deprecated != false) {
size += 2 + 1;
}
if (uninterpretedOption_.Count > 0) {
foreach (global::Google.Protobuf.DescriptorProtos.UninterpretedOption element in uninterpretedOption_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 2 * uninterpretedOption_.Count;
}
size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec);
return size;
}
@ -4081,7 +3953,7 @@ namespace Google.Protobuf.DescriptorProtos {
break;
}
case 7994: {
input.ReadMessageArray(uninterpretedOption_, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser);
uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec);
break;
}
}
@ -4138,6 +4010,8 @@ namespace Google.Protobuf.DescriptorProtos {
}
public const int UninterpretedOptionFieldNumber = 999;
private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> _repeated_uninterpretedOption_codec
= pb::FieldCodec.ForMessage(7994, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser);
private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> UninterpretedOption {
get { return uninterpretedOption_; }
@ -4171,9 +4045,7 @@ namespace Google.Protobuf.DescriptorProtos {
output.WriteRawTag(136, 2);
output.WriteBool(Deprecated);
}
if (uninterpretedOption_.Count > 0) {
output.WriteMessageArray(999, uninterpretedOption_);
}
uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec);
}
public int CalculateSize() {
@ -4181,12 +4053,7 @@ namespace Google.Protobuf.DescriptorProtos {
if (Deprecated != false) {
size += 2 + 1;
}
if (uninterpretedOption_.Count > 0) {
foreach (global::Google.Protobuf.DescriptorProtos.UninterpretedOption element in uninterpretedOption_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 2 * uninterpretedOption_.Count;
}
size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec);
return size;
}
@ -4216,7 +4083,7 @@ namespace Google.Protobuf.DescriptorProtos {
break;
}
case 7994: {
input.ReadMessageArray(uninterpretedOption_, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser);
uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec);
break;
}
}
@ -4268,6 +4135,8 @@ namespace Google.Protobuf.DescriptorProtos {
}
public const int NameFieldNumber = 2;
private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Types.NamePart> _repeated_name_codec
= pb::FieldCodec.ForMessage(18, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Types.NamePart.Parser);
private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Types.NamePart> name_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Types.NamePart>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Types.NamePart> Name {
get { return name_; }
@ -4367,9 +4236,7 @@ namespace Google.Protobuf.DescriptorProtos {
}
public void WriteTo(pb::CodedOutputStream output) {
if (name_.Count > 0) {
output.WriteMessageArray(2, name_);
}
name_.WriteTo(output, _repeated_name_codec);
if (IdentifierValue.Length != 0) {
output.WriteRawTag(26);
output.WriteString(IdentifierValue);
@ -4398,12 +4265,7 @@ namespace Google.Protobuf.DescriptorProtos {
public int CalculateSize() {
int size = 0;
if (name_.Count > 0) {
foreach (global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Types.NamePart element in name_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 1 * name_.Count;
}
size += name_.CalculateSize(_repeated_name_codec);
if (IdentifierValue.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(IdentifierValue);
}
@ -4462,7 +4324,7 @@ namespace Google.Protobuf.DescriptorProtos {
}
break;
case 18: {
input.ReadMessageArray(name_, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Types.NamePart.Parser);
name_.AddEntriesFrom(input, _repeated_name_codec);
break;
}
case 26: {
@ -4676,6 +4538,8 @@ namespace Google.Protobuf.DescriptorProtos {
}
public const int LocationFieldNumber = 1;
private static readonly pb::FieldCodec<global::Google.Protobuf.DescriptorProtos.SourceCodeInfo.Types.Location> _repeated_location_codec
= pb::FieldCodec.ForMessage(10, global::Google.Protobuf.DescriptorProtos.SourceCodeInfo.Types.Location.Parser);
private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.SourceCodeInfo.Types.Location> location_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.SourceCodeInfo.Types.Location>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.SourceCodeInfo.Types.Location> Location {
get { return location_; }
@ -4703,19 +4567,12 @@ namespace Google.Protobuf.DescriptorProtos {
}
public void WriteTo(pb::CodedOutputStream output) {
if (location_.Count > 0) {
output.WriteMessageArray(1, location_);
}
location_.WriteTo(output, _repeated_location_codec);
}
public int CalculateSize() {
int size = 0;
if (location_.Count > 0) {
foreach (global::Google.Protobuf.DescriptorProtos.SourceCodeInfo.Types.Location element in location_) {
size += pb::CodedOutputStream.ComputeMessageSize(element);
}
size += 1 * location_.Count;
}
size += location_.CalculateSize(_repeated_location_codec);
return size;
}
@ -4738,7 +4595,7 @@ namespace Google.Protobuf.DescriptorProtos {
}
break;
case 10: {
input.ReadMessageArray(location_, global::Google.Protobuf.DescriptorProtos.SourceCodeInfo.Types.Location.Parser);
location_.AddEntriesFrom(input, _repeated_location_codec);
break;
}
}
@ -4791,12 +4648,16 @@ namespace Google.Protobuf.DescriptorProtos {
}
public const int PathFieldNumber = 1;
private static readonly pb::FieldCodec<int> _repeated_path_codec
= pb::FieldCodec.ForInt32(10);
private readonly pbc::RepeatedField<int> path_ = new pbc::RepeatedField<int>();
public pbc::RepeatedField<int> Path {
get { return path_; }
}
public const int SpanFieldNumber = 2;
private static readonly pb::FieldCodec<int> _repeated_span_codec
= pb::FieldCodec.ForInt32(18);
private readonly pbc::RepeatedField<int> span_ = new pbc::RepeatedField<int>();
public pbc::RepeatedField<int> Span {
get { return span_; }
@ -4823,6 +4684,8 @@ namespace Google.Protobuf.DescriptorProtos {
}
public const int LeadingDetachedCommentsFieldNumber = 6;
private static readonly pb::FieldCodec<string> _repeated_leadingDetachedComments_codec
= pb::FieldCodec.ForString(50);
private readonly pbc::RepeatedField<string> leadingDetachedComments_ = new pbc::RepeatedField<string>();
public pbc::RepeatedField<string> LeadingDetachedComments {
get { return leadingDetachedComments_; }
@ -4858,14 +4721,8 @@ namespace Google.Protobuf.DescriptorProtos {
}
public void WriteTo(pb::CodedOutputStream output) {
if (path_.Count > 0) {
output.WriteRawTag(10);
output.WritePackedInt32Array(path_);
}
if (span_.Count > 0) {
output.WriteRawTag(18);
output.WritePackedInt32Array(span_);
}
path_.WriteTo(output, _repeated_path_codec);
span_.WriteTo(output, _repeated_span_codec);
if (LeadingComments.Length != 0) {
output.WriteRawTag(26);
output.WriteString(LeadingComments);
@ -4874,43 +4731,20 @@ namespace Google.Protobuf.DescriptorProtos {
output.WriteRawTag(34);
output.WriteString(TrailingComments);
}
if (leadingDetachedComments_.Count > 0) {
output.WriteStringArray(6, leadingDetachedComments_);
}
leadingDetachedComments_.WriteTo(output, _repeated_leadingDetachedComments_codec);
}
public int CalculateSize() {
int size = 0;
if (path_.Count > 0) {
int dataSize = 0;
foreach (int element in path_) {
dataSize += pb::CodedOutputStream.ComputeInt32Size(element);
}
size += dataSize;
size += 1 + pb::CodedOutputStream.ComputeInt32Size(dataSize);
}
if (span_.Count > 0) {
int dataSize = 0;
foreach (int element in span_) {
dataSize += pb::CodedOutputStream.ComputeInt32Size(element);
}
size += dataSize;
size += 1 + pb::CodedOutputStream.ComputeInt32Size(dataSize);
}
size += path_.CalculateSize(_repeated_path_codec);
size += span_.CalculateSize(_repeated_span_codec);
if (LeadingComments.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(LeadingComments);
}
if (TrailingComments.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(TrailingComments);
}
if (leadingDetachedComments_.Count > 0) {
int dataSize = 0;
foreach (string element in leadingDetachedComments_) {
dataSize += pb::CodedOutputStream.ComputeStringSize(element);
}
size += dataSize;
size += 1 * leadingDetachedComments_.Count;
}
size += leadingDetachedComments_.CalculateSize(_repeated_leadingDetachedComments_codec);
return size;
}
@ -4942,12 +4776,12 @@ namespace Google.Protobuf.DescriptorProtos {
break;
case 10:
case 8: {
input.ReadInt32Array(path_);
path_.AddEntriesFrom(input, _repeated_path_codec);
break;
}
case 18:
case 16: {
input.ReadInt32Array(span_);
span_.AddEntriesFrom(input, _repeated_span_codec);
break;
}
case 26: {
@ -4959,7 +4793,7 @@ namespace Google.Protobuf.DescriptorProtos {
break;
}
case 50: {
input.ReadStringArray(leadingDetachedComments_);
leadingDetachedComments_.AddEntriesFrom(input, _repeated_leadingDetachedComments_codec);
break;
}
}

@ -8,6 +8,7 @@ namespace Google.Protobuf
/// </summary>
public static class FieldCodec
{
// TODO: Avoid the "dual hit" of lambda expressions: create open delegates instead. (At least test...)
public static FieldCodec<string> ForString(uint tag)
{
return new FieldCodec<string>(input => input.ReadString(), (output, value) => output.WriteString(value), CodedOutputStream.ComputeStringSize, tag);
@ -84,7 +85,7 @@ namespace Google.Protobuf
}
// Enums are tricky. We can probably use expression trees to build these delegates automatically,
// but it's easy to generate the code fdor it.
// but it's easy to generate the code for it.
public static FieldCodec<T> ForEnum<T>(uint tag, Func<T, int> toInt32, Func<int, T> fromInt32)
{
return new FieldCodec<T>(input => fromInt32(
@ -145,28 +146,68 @@ namespace Google.Protobuf
private readonly Func<CodedInputStream, T> reader;
private readonly Action<CodedOutputStream, T> writer;
private readonly Func<T, int> sizeComputer;
private readonly Func<T, int> sizeCalculator;
private readonly uint tag;
private readonly int tagSize;
private readonly int fixedSize;
internal FieldCodec(
Func<CodedInputStream, T> reader,
Action<CodedOutputStream, T> writer,
Func<T, int> sizeComputer,
Func<T, int> sizeCalculator,
uint tag)
{
this.reader = reader;
this.writer = writer;
this.sizeComputer = sizeComputer;
this.sizeCalculator = sizeCalculator;
this.fixedSize = 0;
this.tag = tag;
tagSize = CodedOutputStream.ComputeRawVarint32Size(tag);
}
internal FieldCodec(
Func<CodedInputStream, T> reader,
Action<CodedOutputStream, T> writer,
int fixedSize,
uint tag)
{
this.reader = reader;
this.writer = writer;
this.sizeCalculator = _ => fixedSize;
this.fixedSize = fixedSize;
this.tag = tag;
tagSize = CodedOutputStream.ComputeRawVarint32Size(tag);
}
/// <summary>
/// Returns the size calculator for just a value.
/// </summary>
internal Func<T, int> ValueSizeCalculator { get { return sizeCalculator; } }
/// <summary>
/// Returns a delegate to write a value (unconditionally) to a coded output stream.
/// </summary>
internal Action<CodedOutputStream, T> ValueWriter { get { return writer; } }
/// <summary>
/// Returns a delegate to read a value from a coded input stream. It is assumed that
/// the stream is already positioned on the appropriate tag.
/// </summary>
internal Func<CodedInputStream, T> ValueReader { get { return reader; } }
/// <summary>
/// Returns the fixed size for an entry, or 0 if sizes vary.
/// </summary>
internal int FixedSize { get { return fixedSize; } }
public uint Tag { get { return tag; } }
public T DefaultValue { get { return Default; } }
public void Write(CodedOutputStream output, T value)
/// <summary>
/// Write a tag and the given value, *if* the value is not the default.
/// </summary>
public void WriteTagAndValue(CodedOutputStream output, T value)
{
if (!IsDefault(value))
{
@ -180,9 +221,13 @@ namespace Google.Protobuf
return reader(input);
}
public int CalculateSize(T value)
/// <summary>
/// Calculates the size required to write the given value, with a tag,
/// if the value is not the default.
/// </summary>
public int CalculateSizeWithTag(T value)
{
return IsDefault(value) ? 0 : sizeComputer(value) + CodedOutputStream.ComputeRawVarint32Size(tag);
return IsDefault(value) ? 0 : sizeCalculator(value) + tagSize;
}
}
}

@ -38,7 +38,7 @@ namespace Google.Protobuf
{
ThrowHelper.ThrowIfNull(message, "message");
ThrowHelper.ThrowIfNull(input, "input");
int size = (int)CodedInputStream.ReadRawVarint32(input);
int size = (int) CodedInputStream.ReadRawVarint32(input);
Stream limitedStream = new LimitedInputStream(input, size);
message.MergeFrom(limitedStream);
}

@ -61,6 +61,13 @@ using System.Security;
[assembly: AssemblyVersion("2.4.1.555")]
[assembly: InternalsVisibleTo("Google.Protobuf.Test, PublicKey=" +
"00240000048000009400000006020000002400005253413100040000110000003b4611704c5379" +
"39c3e0fbe9447dd6fa5462507f9dd4fd9fbf0712457e415b037da6d2c4eb5d2c7d29c86380af68" +
"7cf400401bb183f2a70bd3b631c1fcb7db8aa66c766694a9fb53fa765df6303104da8c978f3b6d" +
"53909cd30685b8bc9922c726cd82b5995e9e2cfca6df7a2d189d851492e49f4b76f269ce6dfd08" +
"c34a7d98")]
#if !NOFILEVERSION
[assembly: AssemblyFileVersion("2.4.1.555")]
#endif

@ -53,13 +53,13 @@ namespace Google.Protobuf
#region Fixed sizes.
// TODO(jonskeet): Move these somewhere else. They're messy. Consider making FieldType a smarter kind of enum
public const int Fixed32Size = 4;
public const int Fixed64Size = 8;
public const int SFixed32Size = 4;
public const int SFixed64Size = 8;
public const int FloatSize = 4;
public const int DoubleSize = 8;
public const int BoolSize = 1;
internal const int Fixed32Size = 4;
internal const int Fixed64Size = 8;
internal const int SFixed32Size = 4;
internal const int SFixed64Size = 8;
internal const int FloatSize = 4;
internal const int DoubleSize = 8;
internal const int BoolSize = 1;
#endregion
@ -72,22 +72,7 @@ namespace Google.Protobuf
EndGroup = 4,
Fixed32 = 5
}
internal static class MessageSetField
{
internal const int Item = 1;
internal const int TypeID = 2;
internal const int Message = 3;
}
internal static class MessageSetTag
{
internal static readonly uint ItemStart = MakeTag(MessageSetField.Item, WireType.StartGroup);
internal static readonly uint ItemEnd = MakeTag(MessageSetField.Item, WireType.EndGroup);
internal static readonly uint TypeID = MakeTag(MessageSetField.TypeID, WireType.Varint);
internal static readonly uint Message = MakeTag(MessageSetField.Message, WireType.LengthDelimited);
}
private const int TagTypeBits = 3;
private const uint TagTypeMask = (1 << TagTypeBits) - 1;
@ -120,7 +105,6 @@ namespace Google.Protobuf
return (uint) (fieldNumber << TagTypeBits) | (uint) wireType;
}
#if !LITE
public static uint MakeTag(FieldDescriptor field)
{
return MakeTag(field.FieldNumber, GetWireType(field));
@ -135,8 +119,6 @@ namespace Google.Protobuf
return descriptor.IsPacked ? WireType.LengthDelimited : GetWireType(descriptor.FieldType);
}
#endif
/// <summary>
/// Converts a field type to its wire type. Done with a switch for the sake
/// of speed - this is significantly faster than a dictionary lookup.
@ -177,7 +159,7 @@ namespace Google.Protobuf
case FieldType.Enum:
return WireType.Varint;
default:
throw new ArgumentOutOfRangeException("No such field type");
throw new ArgumentOutOfRangeException("fieldType", "No such field type");
}
}
}

@ -49,7 +49,6 @@ namespace csharp {
RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
const FieldDescriptor* descriptor, int fieldOrdinal)
: FieldGeneratorBase(descriptor, fieldOrdinal) {
variables_["packed"] = descriptor->is_packed() ? "Packed" : "";
}
RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {
@ -57,6 +56,10 @@ RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {
}
void RepeatedEnumFieldGenerator::GenerateMembers(io::Printer* printer) {
printer->Print(
variables_,
"private static readonly pb::FieldCodec<$type_name$> _repeated_$name$_codec\n"
" = pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x);");
printer->Print(variables_,
"private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n");
AddDeprecatedFlag(printer);
@ -76,53 +79,19 @@ void RepeatedEnumFieldGenerator::GenerateMergingCode(io::Printer* printer) {
void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer) {
printer->Print(
variables_,
"input.ReadEnumArray<$type_name$>($name$_);\n");
"$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n");
}
void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
printer->Print(
variables_,
"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");
"$name$_.WriteTo(output, _repeated_$name$_codec);\n");
}
void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
// TODO(jonskeet): Move all this code into CodedOutputStream? It's a lot to repeat everywhere...
printer->Print(
variables_,
"if ($name$_.Count > 0) {\n");
printer->Indent();
printer->Print("int dataSize = 0;\n");
void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print(
variables_,
"foreach ($type_name$ element in $name$_) {\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$ + pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);\n",
"tag_size", SimpleItoa(tagSize));
} else {
printer->Print(
"size += $tag_size$ * $name$_.Count;\n",
"tag_size", SimpleItoa(tagSize), "name", name());
}
printer->Outdent();
printer->Print("}\n");
"size += $name$_.CalculateSize(_repeated_$name$_codec);\n");
}
void RepeatedEnumFieldGenerator::WriteHash(io::Printer* printer) {

@ -55,6 +55,10 @@ RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {
}
void RepeatedMessageFieldGenerator::GenerateMembers(io::Printer* printer) {
printer->Print(
variables_,
"private static readonly pb::FieldCodec<$type_name$> _repeated_$name$_codec\n"
" = pb::FieldCodec.ForMessage($tag$, $type_name$.Parser);\n");
printer->Print(
variables_,
"private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n");
@ -75,28 +79,19 @@ void RepeatedMessageFieldGenerator::GenerateMergingCode(io::Printer* printer) {
void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer) {
printer->Print(
variables_,
"input.ReadMessageArray($name$_, $type_name$.Parser);\n");
"$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n");
}
void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
// 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"
" output.WriteMessageArray($number$, $name$_);\n"
"}\n");
"$name$_.WriteTo(output, _repeated_$name$_codec);\n");
}
void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($name$_.Count > 0) {\n"
" foreach ($type_name$ element in $name$_) {\n"
" size += pb::CodedOutputStream.ComputeMessageSize(element);\n"
" }\n"
" size += $tag_size$ * $name$_.Count;\n"
"}\n");
"size += $name$_.CalculateSize(_repeated_$name$_codec);\n");
}
void RepeatedMessageFieldGenerator::WriteHash(io::Printer* printer) {

@ -49,7 +49,6 @@ namespace csharp {
RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
const FieldDescriptor* descriptor, int fieldOrdinal)
: FieldGeneratorBase(descriptor, fieldOrdinal) {
variables_["packed"] = descriptor->is_packed() ? "Packed" : "";
}
RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {
@ -57,6 +56,10 @@ RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {
}
void RepeatedPrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) {
printer->Print(
variables_,
"private static readonly pb::FieldCodec<$type_name$> _repeated_$name$_codec\n"
" = pb::FieldCodec.For$capitalized_type_name$($tag$);\n");
printer->Print(variables_,
"private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n");
AddDeprecatedFlag(printer);
@ -74,63 +77,21 @@ void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer)
}
void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) {
printer->Print(variables_,
"input.Read$capitalized_type_name$Array($name$_);\n");
printer->Print(
variables_,
"$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n");
}
void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode(
io::Printer* printer) {
void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
printer->Print(
variables_,
"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");
"$name$_.WriteTo(output, _repeated_$name$_codec);\n");
}
void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode(
io::Printer* printer) {
// TODO(jonskeet): Do this in the runtime if possible. It's a pain, but it must be feasible...
void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print(
"if ($name$_.Count > 0) {\n",
"name", name());
printer->Indent();
printer->Print("int dataSize = 0;\n");
int fixedSize = GetFixedSize(descriptor_->type());
if (fixedSize == -1) {
printer->Print(
variables_,
"foreach ($type_name$ element in $name$_) {\n"
" dataSize += pb::CodedOutputStream.Compute$capitalized_type_name$Size(element);\n"
"}\n");
} else {
printer->Print(
"dataSize = $size$ * $name$_.Count;\n",
"size", SimpleItoa(fixedSize), "name", name());
}
printer->Print("size += dataSize;\n");
int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type());
if (descriptor_->is_packed()) {
printer->Print(
"size += $tag_size$ + pb::CodedOutputStream.ComputeInt32Size(dataSize);\n",
"tag_size", SimpleItoa(tagSize));
} else {
printer->Print(
"size += $tag_size$ * $name$_.Count;\n",
"tag_size", SimpleItoa(tagSize), "name", name());
}
printer->Outdent();
printer->Print("}\n");
variables_,
"size += $name$_.CalculateSize(_repeated_$name$_codec);\n");
}
void RepeatedPrimitiveFieldGenerator::WriteHash(io::Printer* printer) {

Loading…
Cancel
Save