aboutsummaryrefslogtreecommitdiffhomepage
path: root/csharp
diff options
context:
space:
mode:
authorGravatar Jon Skeet <skeet@pobox.com>2008-08-14 20:33:35 +0100
committerGravatar Jon Skeet <skeet@pobox.com>2008-08-14 20:33:35 +0100
commitc0daf107249d95f454d489613de09a4898cefb20 (patch)
treebb95ccdec5b2b6156709ac29febf99ee73087e78 /csharp
parent800f65e20915d3cda9b6b681013dc0a5dd5ddee2 (diff)
Changed fixed size methods to return unsigned integers. Finished FieldSet. Introduced mapping from FieldType to WireType and MappedType.
Diffstat (limited to 'csharp')
-rw-r--r--csharp/ProtocolBuffers.Test/CodedInputStreamTest.cs8
-rw-r--r--csharp/ProtocolBuffers.Test/CodedOutputStreamTest.cs10
-rw-r--r--csharp/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj1
-rw-r--r--csharp/ProtocolBuffers.Test/WireFormatTest.cs20
-rw-r--r--csharp/ProtocolBuffers/AbstractBuilder.cs6
-rw-r--r--csharp/ProtocolBuffers/Autogenerated.cs6
-rw-r--r--csharp/ProtocolBuffers/CodedInputStream.cs83
-rw-r--r--csharp/ProtocolBuffers/CodedOutputStream.cs14
-rw-r--r--csharp/ProtocolBuffers/Descriptors/EnumDescriptor.cs3
-rw-r--r--csharp/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs8
-rw-r--r--csharp/ProtocolBuffers/Descriptors/FieldDescriptor.cs36
-rw-r--r--csharp/ProtocolBuffers/Descriptors/FieldMappingAttribute.cs21
-rw-r--r--csharp/ProtocolBuffers/Descriptors/FieldType.cs40
-rw-r--r--csharp/ProtocolBuffers/Descriptors/FileDescriptor.cs4
-rw-r--r--csharp/ProtocolBuffers/Descriptors/MessageDescriptor.cs8
-rw-r--r--csharp/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs2
-rw-r--r--csharp/ProtocolBuffers/FieldSet.cs249
-rw-r--r--csharp/ProtocolBuffers/GeneratedBuilder.cs12
-rw-r--r--csharp/ProtocolBuffers/IBuilder.cs8
-rw-r--r--csharp/ProtocolBuffers/ProtocolBuffers.csproj2
-rw-r--r--csharp/ProtocolBuffers/UnknownField.cs24
-rw-r--r--csharp/ProtocolBuffers/WireFormat.cs38
22 files changed, 510 insertions, 93 deletions
diff --git a/csharp/ProtocolBuffers.Test/CodedInputStreamTest.cs b/csharp/ProtocolBuffers.Test/CodedInputStreamTest.cs
index 8332140e..c2b2a832 100644
--- a/csharp/ProtocolBuffers.Test/CodedInputStreamTest.cs
+++ b/csharp/ProtocolBuffers.Test/CodedInputStreamTest.cs
@@ -118,7 +118,7 @@ namespace Google.ProtocolBuffers {
/// Parses the given bytes using ReadRawLittleEndian32() and checks
/// that the result matches the given value.
/// </summary>
- private static void AssertReadLittleEndian32(byte[] data, int value) {
+ private static void AssertReadLittleEndian32(byte[] data, uint value) {
CodedInputStream input = CodedInputStream.CreateInstance(data);
Assert.AreEqual(value, input.ReadRawLittleEndian32());
@@ -134,7 +134,7 @@ namespace Google.ProtocolBuffers {
/// Parses the given bytes using ReadRawLittleEndian64() and checks
/// that the result matches the given value.
/// </summary>
- private static void AssertReadLittleEndian64(byte[] data, long value) {
+ private static void AssertReadLittleEndian64(byte[] data, ulong value) {
CodedInputStream input = CodedInputStream.CreateInstance(data);
Assert.AreEqual(value, input.ReadRawLittleEndian64());
@@ -149,12 +149,12 @@ namespace Google.ProtocolBuffers {
[Test]
public void ReadLittleEndian() {
AssertReadLittleEndian32(Bytes(0x78, 0x56, 0x34, 0x12), 0x12345678);
- AssertReadLittleEndian32(Bytes(0xf0, 0xde, 0xbc, 0x9a), unchecked((int)0x9abcdef0));
+ AssertReadLittleEndian32(Bytes(0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef0);
AssertReadLittleEndian64(Bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12),
0x123456789abcdef0L);
AssertReadLittleEndian64(
- Bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a), unchecked((long)0x9abcdef012345678L));
+ Bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef012345678UL);
}
[Test]
diff --git a/csharp/ProtocolBuffers.Test/CodedOutputStreamTest.cs b/csharp/ProtocolBuffers.Test/CodedOutputStreamTest.cs
index 0e97f2fd..f2f00dfe 100644
--- a/csharp/ProtocolBuffers.Test/CodedOutputStreamTest.cs
+++ b/csharp/ProtocolBuffers.Test/CodedOutputStreamTest.cs
@@ -106,7 +106,7 @@ namespace Google.ProtocolBuffers {
AssertWriteVarint(
Bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49),
(0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
- (0x43L << 28) | (0x49L << 35) | (0x24L << 42) | (0x49L << 49));
+ (0x43UL << 28) | (0x49L << 35) | (0x24UL << 42) | (0x49UL << 49));
// 11964378330978735131
AssertWriteVarint(
Bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01),
@@ -120,7 +120,7 @@ namespace Google.ProtocolBuffers {
/// Parses the given bytes using WriteRawLittleEndian32() and checks
/// that the result matches the given value.
/// </summary>
- private static void AssertWriteLittleEndian32(byte[] data, int value) {
+ private static void AssertWriteLittleEndian32(byte[] data, uint value) {
MemoryStream rawOutput = new MemoryStream();
CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
output.WriteRawLittleEndian32(value);
@@ -141,7 +141,7 @@ namespace Google.ProtocolBuffers {
/// Parses the given bytes using WriteRawLittleEndian64() and checks
/// that the result matches the given value.
/// </summary>
- private static void AssertWriteLittleEndian64(byte[] data, long value) {
+ private static void AssertWriteLittleEndian64(byte[] data, ulong value) {
MemoryStream rawOutput = new MemoryStream();
CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
output.WriteRawLittleEndian64(value);
@@ -164,14 +164,14 @@ namespace Google.ProtocolBuffers {
[Test]
public void WriteLittleEndian() {
AssertWriteLittleEndian32(Bytes(0x78, 0x56, 0x34, 0x12), 0x12345678);
- AssertWriteLittleEndian32(Bytes(0xf0, 0xde, 0xbc, 0x9a), unchecked((int)0x9abcdef0));
+ AssertWriteLittleEndian32(Bytes(0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef0);
AssertWriteLittleEndian64(
Bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12),
0x123456789abcdef0L);
AssertWriteLittleEndian64(
Bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a),
- unchecked((long)0x9abcdef012345678L));
+ 0x9abcdef012345678UL);
}
/* TODO(jonskeet): Put this back when we've got the rest working!
diff --git a/csharp/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj b/csharp/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
index 89c5507a..28c86b3c 100644
--- a/csharp/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
+++ b/csharp/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
@@ -48,6 +48,7 @@
<Compile Include="CodedInputStreamTest.cs" />
<Compile Include="CodedOutputStreamTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="WireFormatTest.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ProtocolBuffers\ProtocolBuffers.csproj">
diff --git a/csharp/ProtocolBuffers.Test/WireFormatTest.cs b/csharp/ProtocolBuffers.Test/WireFormatTest.cs
new file mode 100644
index 00000000..87c9dc6d
--- /dev/null
+++ b/csharp/ProtocolBuffers.Test/WireFormatTest.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using NUnit.Framework;
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers {
+ [TestFixture]
+ public class WireFormatTest {
+
+ [Test]
+ public void FieldTypeToWireTypeMapping() {
+
+ // Just test a few values
+ Assert.AreEqual(WireFormat.WireType.Fixed64, WireFormat.FieldTypeToWireFormatMap[FieldType.SFixed64]);
+ Assert.AreEqual(WireFormat.WireType.LengthDelimited, WireFormat.FieldTypeToWireFormatMap[FieldType.String]);
+ Assert.AreEqual(WireFormat.WireType.LengthDelimited, WireFormat.FieldTypeToWireFormatMap[FieldType.Message]);
+ }
+ }
+}
diff --git a/csharp/ProtocolBuffers/AbstractBuilder.cs b/csharp/ProtocolBuffers/AbstractBuilder.cs
index f8ed554d..8a8554e4 100644
--- a/csharp/ProtocolBuffers/AbstractBuilder.cs
+++ b/csharp/ProtocolBuffers/AbstractBuilder.cs
@@ -25,7 +25,7 @@ namespace Google.ProtocolBuffers {
protected abstract IMessage BuildPartialImpl();
protected abstract IBuilder CloneImpl();
protected abstract IMessage DefaultInstanceForTypeImpl { get; }
- protected abstract IBuilder NewBuilderForFieldImpl(FieldDescriptor field);
+ protected abstract IBuilder CreateBuilderForFieldImpl(FieldDescriptor field);
protected abstract IBuilder ClearFieldImpl(FieldDescriptor field);
protected abstract IBuilder AddRepeatedFieldImpl(FieldDescriptor field, object value);
#endregion
@@ -47,8 +47,8 @@ namespace Google.ProtocolBuffers {
get { return DefaultInstanceForTypeImpl; }
}
- IBuilder IBuilder.NewBuilderForField(FieldDescriptor field) {
- return NewBuilderForFieldImpl(field);
+ IBuilder IBuilder.CreateBuilderForField(FieldDescriptor field) {
+ return CreateBuilderForFieldImpl(field);
}
IBuilder IBuilder.ClearField(FieldDescriptor field) {
diff --git a/csharp/ProtocolBuffers/Autogenerated.cs b/csharp/ProtocolBuffers/Autogenerated.cs
index 5b999787..e4aee669 100644
--- a/csharp/ProtocolBuffers/Autogenerated.cs
+++ b/csharp/ProtocolBuffers/Autogenerated.cs
@@ -5,5 +5,11 @@ namespace Google.ProtocolBuffers {
public class MessageOptions {
public bool IsMessageSetWireFormat;
}
+
+ public class EnumValueDescriptorProto {
+ }
+
+ public class FieldDescriptorProto {
+ }
}
}
diff --git a/csharp/ProtocolBuffers/CodedInputStream.cs b/csharp/ProtocolBuffers/CodedInputStream.cs
index d2a3657b..ff5d6f88 100644
--- a/csharp/ProtocolBuffers/CodedInputStream.cs
+++ b/csharp/ProtocolBuffers/CodedInputStream.cs
@@ -142,7 +142,7 @@ namespace Google.ProtocolBuffers {
/// Read a double field from the stream.
/// </summary>
public double ReadDouble() {
- return BitConverter.Int64BitsToDouble(ReadRawLittleEndian64());
+ return BitConverter.Int64BitsToDouble((long) ReadRawLittleEndian64());
}
/// <summary>
@@ -178,14 +178,14 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Read a fixed64 field from the stream.
/// </summary>
- public long ReadFixed64() {
+ public ulong ReadFixed64() {
return ReadRawLittleEndian64();
}
/// <summary>
/// Read a fixed32 field from the stream.
/// </summary>
- public int ReadFixed32() {
+ public uint ReadFixed32() {
return ReadRawLittleEndian32();
}
@@ -293,14 +293,14 @@ namespace Google.ProtocolBuffers {
/// Reads an sfixed32 field value from the stream.
/// </summary>
public int ReadSFixed32() {
- return ReadRawLittleEndian32();
+ return (int) ReadRawLittleEndian32();
}
/// <summary>
/// Reads an sfixed64 field value from the stream.
/// </summary>
public long ReadSFixed64() {
- return ReadRawLittleEndian64();
+ return (long) ReadRawLittleEndian64();
}
/// <summary>
@@ -410,26 +410,26 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Read a 32-bit little-endian integer from the stream.
/// </summary>
- public int ReadRawLittleEndian32() {
- byte b1 = ReadRawByte();
- byte b2 = ReadRawByte();
- byte b3 = ReadRawByte();
- byte b4 = ReadRawByte();
+ public uint ReadRawLittleEndian32() {
+ uint b1 = ReadRawByte();
+ uint b2 = ReadRawByte();
+ uint b3 = ReadRawByte();
+ uint b4 = ReadRawByte();
return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24);
}
/// <summary>
/// Read a 64-bit little-endian integer from the stream.
/// </summary>
- public long ReadRawLittleEndian64() {
- long b1 = ReadRawByte();
- long b2 = ReadRawByte();
- long b3 = ReadRawByte();
- long b4 = ReadRawByte();
- long b5 = ReadRawByte();
- long b6 = ReadRawByte();
- long b7 = ReadRawByte();
- long b8 = ReadRawByte();
+ public ulong ReadRawLittleEndian64() {
+ ulong b1 = ReadRawByte();
+ ulong b2 = ReadRawByte();
+ ulong b3 = ReadRawByte();
+ ulong b4 = ReadRawByte();
+ ulong b5 = ReadRawByte();
+ ulong b6 = ReadRawByte();
+ ulong b7 = ReadRawByte();
+ ulong b8 = ReadRawByte();
return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24)
| (b5 << 32) | (b6 << 40) | (b7 << 48) | (b8 << 56);
}
@@ -706,6 +706,51 @@ namespace Google.ProtocolBuffers {
}
/// <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) {
+ switch (WireFormat.GetTagWireType(tag)) {
+ case WireFormat.WireType.Varint:
+ ReadInt32();
+ 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() {
+ while (true) {
+ uint tag = ReadTag();
+ if (tag == 0 || !SkipField(tag)) {
+ return;
+ }
+ }
+ }
+
+ /// <summary>
/// Reads and discards <paramref name="size"/> bytes.
/// </summary>
/// <exception cref="InvalidProtocolBufferException">the end of the stream
diff --git a/csharp/ProtocolBuffers/CodedOutputStream.cs b/csharp/ProtocolBuffers/CodedOutputStream.cs
index 5fec5274..260db868 100644
--- a/csharp/ProtocolBuffers/CodedOutputStream.cs
+++ b/csharp/ProtocolBuffers/CodedOutputStream.cs
@@ -99,7 +99,7 @@ namespace Google.ProtocolBuffers {
/// </summary>
public void WriteDouble(int fieldNumber, double value) {
WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
- WriteRawLittleEndian64(BitConverter.DoubleToInt64Bits(value));
+ WriteRawLittleEndian64((ulong)BitConverter.DoubleToInt64Bits(value));
}
/// <summary>
@@ -143,7 +143,7 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Writes a fixed64 field value, including tag, to the stream.
/// </summary>
- public void WriteFixed64(int fieldNumber, long value) {
+ public void WriteFixed64(int fieldNumber, ulong value) {
WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
WriteRawLittleEndian64(value);
}
@@ -151,7 +151,7 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Writes a fixed32 field value, including tag, to the stream.
/// </summary>
- public void WriteFixed32(int fieldNumber, int value) {
+ public void WriteFixed32(int fieldNumber, uint value) {
WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
WriteRawLittleEndian32(value);
}
@@ -259,8 +259,8 @@ namespace Google.ProtocolBuffers {
case FieldType.Int64: WriteInt64(fieldNumber, (long)value); break;
case FieldType.UInt64: WriteUInt64(fieldNumber, (ulong)value); break;
case FieldType.Int32: WriteInt32(fieldNumber, (int)value); break;
- case FieldType.Fixed64: WriteFixed64(fieldNumber, (long)value); break;
- case FieldType.Fixed32: WriteFixed32(fieldNumber, (int)value); break;
+ case FieldType.Fixed64: WriteFixed64(fieldNumber, (ulong)value); break;
+ case FieldType.Fixed32: WriteFixed32(fieldNumber, (uint)value); break;
case FieldType.Bool: WriteBool(fieldNumber, (bool)value); break;
case FieldType.String: WriteString(fieldNumber, (string)value); break;
case FieldType.Group: WriteGroup(fieldNumber, (IMessage)value); break;
@@ -310,14 +310,14 @@ namespace Google.ProtocolBuffers {
}
}
- public void WriteRawLittleEndian32(int value) {
+ public void WriteRawLittleEndian32(uint value) {
WriteRawByte((byte)value);
WriteRawByte((byte)(value >> 8));
WriteRawByte((byte)(value >> 16));
WriteRawByte((byte)(value >> 24));
}
- public void WriteRawLittleEndian64(long value) {
+ public void WriteRawLittleEndian64(ulong value) {
WriteRawByte((byte)value);
WriteRawByte((byte)(value >> 8));
WriteRawByte((byte)(value >> 16));
diff --git a/csharp/ProtocolBuffers/Descriptors/EnumDescriptor.cs b/csharp/ProtocolBuffers/Descriptors/EnumDescriptor.cs
index c4f5c796..2d27b1f0 100644
--- a/csharp/ProtocolBuffers/Descriptors/EnumDescriptor.cs
+++ b/csharp/ProtocolBuffers/Descriptors/EnumDescriptor.cs
@@ -1,5 +1,8 @@

namespace Google.ProtocolBuffers.Descriptors {
public class EnumDescriptor {
+ internal EnumValueDescriptor FindValueByNumber(int rawValue) {
+ throw new System.NotImplementedException();
+ }
}
}
diff --git a/csharp/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs b/csharp/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs
index 48b3fb5c..faa83fd4 100644
--- a/csharp/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs
+++ b/csharp/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs
@@ -2,6 +2,14 @@
namespace Google.ProtocolBuffers.Descriptors {
public class EnumValueDescriptor {
+
+ internal EnumValueDescriptor(DescriptorProtos.EnumValueDescriptorProto proto,
+ FileDescriptor file,
+ EnumDescriptor parent,
+ int index) {
+ enumDescriptor = parent;
+ }
+
private EnumDescriptor enumDescriptor;
public int Number {
diff --git a/csharp/ProtocolBuffers/Descriptors/FieldDescriptor.cs b/csharp/ProtocolBuffers/Descriptors/FieldDescriptor.cs
index 45e7f964..cd2f19b1 100644
--- a/csharp/ProtocolBuffers/Descriptors/FieldDescriptor.cs
+++ b/csharp/ProtocolBuffers/Descriptors/FieldDescriptor.cs
@@ -1,9 +1,19 @@
-
-using System;
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using Google.ProtocolBuffers.Collections;
namespace Google.ProtocolBuffers.Descriptors {
public class FieldDescriptor {
+ private FieldDescriptor(DescriptorProtos.FieldDescriptorProto proto,
+ FileDescriptor file,
+ MessageDescriptor parent,
+ int index,
+ bool isExtension) {
+ enumType = null;
+ }
+
private EnumDescriptor enumType;
public bool IsRequired {
@@ -47,14 +57,28 @@ namespace Google.ProtocolBuffers.Descriptors {
/// this will always be an empty list. For message fields it will
/// always be null. For singular values, it will depend on the descriptor.
/// </summary>
- public object DefaultValue
- {
+ public object DefaultValue {
get { throw new NotImplementedException(); }
}
- public string Name
- {
+ public string Name {
get { throw new NotImplementedException(); }
}
+
+ /// <summary>
+ /// Immutable mapping from field type to mapped type. Built using the attributes on
+ /// FieldType values.
+ /// </summary>
+ public static readonly IDictionary<FieldType, MappedType> FieldTypeToWireFormatMap = MapFieldTypes();
+
+ private static IDictionary<FieldType, MappedType> MapFieldTypes() {
+ var map = new Dictionary<FieldType, MappedType>();
+ foreach (FieldInfo field in typeof(FieldType).GetFields(BindingFlags.Static | BindingFlags.Public)) {
+ FieldType fieldType = (FieldType)field.GetValue(null);
+ FieldMappingAttribute mapping = (FieldMappingAttribute)field.GetCustomAttributes(typeof(FieldMappingAttribute), false)[0];
+ map[fieldType] = mapping.MappedType;
+ }
+ return Dictionaries.AsReadOnly(map);
+ }
}
}
diff --git a/csharp/ProtocolBuffers/Descriptors/FieldMappingAttribute.cs b/csharp/ProtocolBuffers/Descriptors/FieldMappingAttribute.cs
new file mode 100644
index 00000000..13e8be1e
--- /dev/null
+++ b/csharp/ProtocolBuffers/Descriptors/FieldMappingAttribute.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Google.ProtocolBuffers.Descriptors {
+
+ /// <summary>
+ /// Defined specifically for the <see cref="FieldType" /> enumeration,
+ /// this allows each field type to specify the mapped type and wire type.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Field)]
+ internal class FieldMappingAttribute : Attribute {
+ internal FieldMappingAttribute(MappedType mappedType, WireFormat.WireType wireType) {
+ MappedType = mappedType;
+ WireType = wireType;
+ }
+
+ internal MappedType MappedType { get; private set; }
+ internal WireFormat.WireType WireType { get; private set; }
+ }
+}
diff --git a/csharp/ProtocolBuffers/Descriptors/FieldType.cs b/csharp/ProtocolBuffers/Descriptors/FieldType.cs
index d54ded53..30b82d69 100644
--- a/csharp/ProtocolBuffers/Descriptors/FieldType.cs
+++ b/csharp/ProtocolBuffers/Descriptors/FieldType.cs
@@ -1,23 +1,27 @@

namespace Google.ProtocolBuffers.Descriptors {
+ /// <summary>
+ /// Enumeration of all the possible field types. The odd formatting is to make it very clear
+ /// which attribute applies to which value, while maintaining a compact format.
+ /// </summary>
public enum FieldType {
- Double,
- Float,
- Int64,
- UInt64,
- Int32,
- Fixed64,
- Fixed32,
- Bool,
- String,
- Group,
- Message,
- Bytes,
- UInt32,
- SFixed32,
- SFixed64,
- SInt32,
- SInt64,
- Enum
+ [FieldMapping(MappedType.Double, WireFormat.WireType.Fixed64)] Double,
+ [FieldMapping(MappedType.Single, WireFormat.WireType.Fixed32)] Float,
+ [FieldMapping(MappedType.Int64, WireFormat.WireType.Varint)] Int64,
+ [FieldMapping(MappedType.UInt64, WireFormat.WireType.Varint)] UInt64,
+ [FieldMapping(MappedType.Int32, WireFormat.WireType.Varint)] Int32,
+ [FieldMapping(MappedType.UInt64, WireFormat.WireType.Fixed64)] Fixed64,
+ [FieldMapping(MappedType.UInt32, WireFormat.WireType.Fixed32)] Fixed32,
+ [FieldMapping(MappedType.Boolean, WireFormat.WireType.Varint)] Bool,
+ [FieldMapping(MappedType.String, WireFormat.WireType.LengthDelimited)] String,
+ [FieldMapping(MappedType.Message, WireFormat.WireType.StartGroup)] Group,
+ [FieldMapping(MappedType.Message, WireFormat.WireType.LengthDelimited)] Message,
+ [FieldMapping(MappedType.ByteString, WireFormat.WireType.LengthDelimited)] Bytes,
+ [FieldMapping(MappedType.UInt32, WireFormat.WireType.Varint)] UInt32,
+ [FieldMapping(MappedType.Int32, WireFormat.WireType.Fixed32)] SFixed32,
+ [FieldMapping(MappedType.Int64, WireFormat.WireType.Fixed64)] SFixed64,
+ [FieldMapping(MappedType.Int32, WireFormat.WireType.Varint)] SInt32,
+ [FieldMapping(MappedType.Int64, WireFormat.WireType.Varint)] SInt64,
+ [FieldMapping(MappedType.Enum, WireFormat.WireType.Varint)] Enum
}
}
diff --git a/csharp/ProtocolBuffers/Descriptors/FileDescriptor.cs b/csharp/ProtocolBuffers/Descriptors/FileDescriptor.cs
new file mode 100644
index 00000000..0aaca886
--- /dev/null
+++ b/csharp/ProtocolBuffers/Descriptors/FileDescriptor.cs
@@ -0,0 +1,4 @@
+namespace Google.ProtocolBuffers.Descriptors {
+ class FileDescriptor {
+ }
+}
diff --git a/csharp/ProtocolBuffers/Descriptors/MessageDescriptor.cs b/csharp/ProtocolBuffers/Descriptors/MessageDescriptor.cs
index 4e0834f0..df2972f6 100644
--- a/csharp/ProtocolBuffers/Descriptors/MessageDescriptor.cs
+++ b/csharp/ProtocolBuffers/Descriptors/MessageDescriptor.cs
@@ -6,5 +6,13 @@ namespace Google.ProtocolBuffers.Descriptors {
public IList<FieldDescriptor> Fields;
public DescriptorProtos.MessageOptions Options;
public string FullName;
+
+ internal bool IsExtensionNumber(int fieldNumber) {
+ throw new System.NotImplementedException();
+ }
+
+ internal FieldDescriptor FindFieldByNumber(int fieldNumber) {
+ throw new System.NotImplementedException();
+ }
}
}
diff --git a/csharp/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs b/csharp/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs
index d7b239c1..cf5220f6 100644
--- a/csharp/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs
+++ b/csharp/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs
@@ -1,6 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Text;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.FieldAccess {
diff --git a/csharp/ProtocolBuffers/FieldSet.cs b/csharp/ProtocolBuffers/FieldSet.cs
index 9ab13c65..4ad94417 100644
--- a/csharp/ProtocolBuffers/FieldSet.cs
+++ b/csharp/ProtocolBuffers/FieldSet.cs
@@ -104,14 +104,195 @@ namespace Google.ProtocolBuffers {
}
// TODO(jonskeet): Should this be in UnknownFieldSet.Builder really?
+ /// <summary>
+ /// Like <see cref="MergeFrom(CodedInputStream, UnknownFieldSet.Builder, ExtensionRegistry, IBuilder)" />
+ /// but parses a single field.
+ /// </summary>
+ /// <param name="input">The input to read the field from</param>
+ /// <param name="unknownFields">The set of unknown fields to add the newly-read field to</param>
+ /// <param name="extensionRegistry">Registry to use when an extension field is encountered</param>
+ /// <param name="builder">A builder (???)</param>
+ /// <param name="tag">The tag, which should already have been read from the input</param>
+ /// <returns>true unless the tag is an end-group tag</returns>
internal static bool MergeFieldFrom(CodedInputStream input,
UnknownFieldSet.Builder unknownFields,
ExtensionRegistry extensionRegistry,
IBuilder builder,
uint tag) {
- throw new NotImplementedException();
+ MessageDescriptor type = builder.DescriptorForType;
+
+ if (type.Options.IsMessageSetWireFormat
+ && tag == WireFormat.MessageSetTag.ItemStart) {
+ MergeMessageSetExtensionFromCodedStream(input, unknownFields, extensionRegistry, builder);
+ return true;
+ }
+
+ WireFormat.WireType wireType = WireFormat.GetTagWireType(tag);
+ int fieldNumber = WireFormat.GetTagFieldNumber(tag);
+
+ FieldDescriptor field;
+ IMessage defaultInstance = null;
+
+ if (type.IsExtensionNumber(fieldNumber)) {
+ ExtensionInfo extension = extensionRegistry[type, fieldNumber];
+ if (extension == null) {
+ field = null;
+ } else {
+ field = extension.Descriptor;
+ defaultInstance = extension.DefaultInstance;
+ }
+ } else {
+ field = type.FindFieldByNumber(fieldNumber);
+ }
+
+ // Unknown field or wrong wire type. Skip.
+ if (field == null || wireType != WireFormat.FieldTypeToWireFormatMap[field.FieldType]) {
+ return unknownFields.MergeFieldFrom(tag, input);
+ }
+
+ object value;
+ switch (field.FieldType) {
+ case FieldType.Group:
+ case FieldType.Message: {
+ IBuilder subBuilder;
+ if (defaultInstance != null) {
+ subBuilder = defaultInstance.CreateBuilderForType();
+ } else {
+ subBuilder = builder.CreateBuilderForField(field);
+ }
+ if (!field.IsRepeated) {
+ subBuilder.MergeFrom((IMessage) builder[field]);
+ }
+ if (field.FieldType == FieldType.Group) {
+ input.ReadGroup(field.FieldNumber, subBuilder, extensionRegistry);
+ } else {
+ input.ReadMessage(subBuilder, extensionRegistry);
+ }
+ value = subBuilder.Build();
+ break;
+ }
+ case FieldType.Enum: {
+ int rawValue = input.ReadEnum();
+ value = field.EnumType.FindValueByNumber(rawValue);
+ // If the number isn't recognized as a valid value for this enum,
+ // drop it.
+ if (value == null) {
+ unknownFields.MergeVarintField(fieldNumber, (ulong) rawValue);
+ return true;
+ }
+ break;
+ }
+ default:
+ value = input.ReadPrimitiveField(field.FieldType);
+ break;
+ }
+ if (field.IsRepeated) {
+ builder.AddRepeatedField(field, value);
+ } else {
+ builder[field] = value;
+ }
+ return true;
}
+ // TODO(jonskeet): Move to UnknownFieldSet.Builder?
+ /// <summary>
+ /// Called by MergeFieldFrom to parse a MessageSet extension.
+ /// </summary>
+ private static void MergeMessageSetExtensionFromCodedStream(CodedInputStream input,
+ UnknownFieldSet.Builder unknownFields,
+ ExtensionRegistry extensionRegistry,
+ IBuilder builder) {
+ MessageDescriptor type = builder.DescriptorForType;
+
+ // The wire format for MessageSet is:
+ // message MessageSet {
+ // repeated group Item = 1 {
+ // required int32 typeId = 2;
+ // required bytes message = 3;
+ // }
+ // }
+ // "typeId" is the extension's field number. The extension can only be
+ // a message type, where "message" contains the encoded bytes of that
+ // message.
+ //
+ // In practice, we will probably never see a MessageSet item in which
+ // the message appears before the type ID, or where either field does not
+ // appear exactly once. However, in theory such cases are valid, so we
+ // should be prepared to accept them.
+
+ int typeId = 0;
+ ByteString rawBytes = null; // If we encounter "message" before "typeId"
+ IBuilder subBuilder = null;
+ FieldDescriptor field = null;
+
+ while (true) {
+ uint tag = input.ReadTag();
+ if (tag == 0) {
+ break;
+ }
+
+ if (tag == WireFormat.MessageSetTag.TypeID) {
+ typeId = input.ReadInt32();
+ // Zero is not a valid type ID.
+ if (typeId != 0) {
+ ExtensionInfo extension = extensionRegistry[type, typeId];
+ if (extension != null) {
+ field = extension.Descriptor;
+ subBuilder = extension.DefaultInstance.CreateBuilderForType();
+ IMessage originalMessage = (IMessage) builder[field];
+ if (originalMessage != null) {
+ subBuilder.MergeFrom(originalMessage);
+ }
+ if (rawBytes != null) {
+ // We already encountered the message. Parse it now.
+ // TODO(jonskeet): Check this is okay. It's subtly different from the Java, as it doesn't create an input stream from rawBytes.
+ // In fact, why don't we just call MergeFrom(rawBytes)? And what about the extension registry?
+ subBuilder.MergeFrom(rawBytes.CreateCodedInput());
+ rawBytes = null;
+ }
+ } else {
+ // Unknown extension number. If we already saw data, put it
+ // in rawBytes.
+ if (rawBytes != null) {
+ unknownFields.MergeField(typeId,
+ UnknownField.CreateBuilder()
+ .AddLengthDelimited(rawBytes)
+ .Build());
+ rawBytes = null;
+ }
+ }
+ }
+ } else if (tag == WireFormat.MessageSetTag.Message) {
+ if (typeId == 0) {
+ // We haven't seen a type ID yet, so we have to store the raw bytes for now.
+ rawBytes = input.ReadBytes();
+ } else if (subBuilder == null) {
+ // We don't know how to parse this. Ignore it.
+ unknownFields.MergeField(typeId,
+ UnknownField.CreateBuilder()
+ .AddLengthDelimited(input.ReadBytes())
+ .Build());
+ } else {
+ // We already know the type, so we can parse directly from the input
+ // with no copying. Hooray!
+ input.ReadMessage(subBuilder, extensionRegistry);
+ }
+ } else {
+ // Unknown tag. Skip it.
+ if (!input.SkipField(tag)) {
+ break; // end of group
+ }
+ }
+ }
+
+ input.CheckLastTagWas(WireFormat.MessageSetTag.ItemEnd);
+
+ if (subBuilder != null) {
+ builder[field] = subBuilder.Build();
+ }
+ }
+
+
/// <summary>
/// Clears all fields.
/// </summary>
@@ -120,7 +301,7 @@ namespace Google.ProtocolBuffers {
}
/// <summary>
- /// <see cref="IMessage.Item(FieldDescriptor)"/>
+ /// See <see cref="IMessage.Item(FieldDescriptor)"/>
/// </summary>
/// <remarks>
/// If the field is not set, the behaviour when fetching this property varies by field type:
@@ -172,7 +353,7 @@ namespace Google.ProtocolBuffers {
}
/// <summary>
- /// <see cref="IMessage.Item(FieldDescriptor,int)" />
+ /// See <see cref="IMessage.Item(FieldDescriptor,int)" />
/// </summary>
internal object this[FieldDescriptor field, int index] {
get {
@@ -196,7 +377,7 @@ namespace Google.ProtocolBuffers {
}
/// <summary>
- /// <see cref="IBuilder.AddRepeatedField" />
+ /// See <see cref="IBuilder.AddRepeatedField" />
/// </summary>
/// <param name="field"></param>
/// <param name="value"></param>
@@ -214,7 +395,7 @@ namespace Google.ProtocolBuffers {
}
/// <summary>
- /// <see cref="IMessage.IsInitialized" />
+ /// See <see cref="IMessage.IsInitialized" />
/// </summary>
/// <remarks>
/// Since FieldSet itself does not have any way of knowing about
@@ -259,14 +440,14 @@ namespace Google.ProtocolBuffers {
}
/// <summary>
- /// <see cref="IBuilder.ClearField" />
+ /// See <see cref="IBuilder.ClearField" />
/// </summary>
public void ClearField(FieldDescriptor field) {
fields.Remove(field);
}
/// <summary>
- /// <see cref="IMessage.GetRepeatedFieldCount" />
+ /// See <see cref="IMessage.GetRepeatedFieldCount" />
/// </summary>
public int GetRepeatedFieldCount(FieldDescriptor field) {
if (!field.IsRepeated) {
@@ -277,6 +458,60 @@ namespace Google.ProtocolBuffers {
}
/// <summary>
+ /// Implementation of both <c>MergeFrom</c> methods.
+ /// </summary>
+ /// <param name="otherFields"></param>
+ private void MergeFields(IEnumerable<KeyValuePair<FieldDescriptor, object>> otherFields) {
+ // Note: We don't attempt to verify that other's fields have valid
+ // types. Doing so would be a losing battle. We'd have to verify
+ // all sub-messages as well, and we'd have to make copies of all of
+ // them to insure that they don't change after verification (since
+ // the IMessage interface itself cannot enforce immutability of
+ // implementations).
+ // TODO(jonskeet): Provide a function somewhere called MakeDeepCopy()
+ // which allows people to make secure deep copies of messages.
+
+ foreach (KeyValuePair<FieldDescriptor, object> entry in otherFields) {
+ FieldDescriptor field = entry.Key;
+ object existingValue;
+ fields.TryGetValue(field, out existingValue);
+ if (field.IsRepeated) {
+ if (existingValue == null) {
+ existingValue = new List<object>();
+ fields[field] = existingValue;
+ }
+ List<object> list = (List<object>)existingValue;
+ foreach (object otherValue in (IEnumerable)entry.Value) {
+ list.Add(otherValue);
+ }
+ } else if (field.MappedType == MappedType.Message && existingValue != null) {
+ IMessage existingMessage = (IMessage)existingValue;
+ IMessage merged = existingMessage.CreateBuilderForType()
+ .MergeFrom(existingMessage)
+ .MergeFrom((IMessage)entry.Value)
+ .Build();
+ this[field] = merged;
+ } else {
+ this[field] = entry.Value;
+ }
+ }
+ }
+
+ /// <summary>
+ /// See <see cref="IBuilder.MergeFrom(IMessage)" />
+ /// </summary>
+ public void MergeFrom(IMessage other) {
+ MergeFields(other.AllFields);
+ }
+
+ /// <summary>
+ /// Like <see cref="MergeFrom(IMessage)"/>, but merges from another <c>FieldSet</c>.
+ /// </summary>
+ public void MergeFrom(FieldSet other) {
+ MergeFields(other.fields);
+ }
+
+ /// <summary>
/// Verifies that the given object is of the correct type to be a valid
/// value for the given field.
/// </summary>
diff --git a/csharp/ProtocolBuffers/GeneratedBuilder.cs b/csharp/ProtocolBuffers/GeneratedBuilder.cs
index ffb794f6..a98dbccc 100644
--- a/csharp/ProtocolBuffers/GeneratedBuilder.cs
+++ b/csharp/ProtocolBuffers/GeneratedBuilder.cs
@@ -73,8 +73,8 @@ namespace Google.ProtocolBuffers {
get { return DefaultInstanceForType; }
}
- protected override IBuilder NewBuilderForFieldImpl(FieldDescriptor field) {
- return NewBuilderForField(field);
+ protected override IBuilder CreateBuilderForFieldImpl(FieldDescriptor field) {
+ return CreateBuilderForField(field);
}
protected override IBuilder ClearFieldImpl(FieldDescriptor field) {
@@ -91,9 +91,9 @@ namespace Google.ProtocolBuffers {
throw new NotImplementedException();
}
- public abstract IMessage<TMessage> Build();
+ public abstract TMessage Build();
- public abstract IMessage<TMessage> BuildPartial();
+ public abstract TMessage BuildPartial();
public abstract IBuilder<TMessage> Clone();
@@ -105,11 +105,11 @@ namespace Google.ProtocolBuffers {
throw new NotImplementedException();
}
- public IMessage<TMessage> DefaultInstanceForType {
+ public TMessage DefaultInstanceForType {
get { throw new NotImplementedException(); }
}
- public IBuilder NewBuilderForField(FieldDescriptor field) {
+ public IBuilder CreateBuilderForField(FieldDescriptor field) {
throw new NotImplementedException();
}
diff --git a/csharp/ProtocolBuffers/IBuilder.cs b/csharp/ProtocolBuffers/IBuilder.cs
index f1366988..02b3b59b 100644
--- a/csharp/ProtocolBuffers/IBuilder.cs
+++ b/csharp/ProtocolBuffers/IBuilder.cs
@@ -88,7 +88,7 @@ namespace Google.ProtocolBuffers {
IBuilder MergeFrom(CodedInputStream input);
IBuilder MergeFrom(CodedInputStream codedInputStream, ExtensionRegistry extensionRegistry);
IMessage DefaultInstanceForType { get; }
- IBuilder NewBuilderForField(FieldDescriptor field);
+ IBuilder CreateBuilderForField(FieldDescriptor field);
IBuilder ClearField(FieldDescriptor field);
IBuilder AddRepeatedField(FieldDescriptor field, object value);
IBuilder MergeUnknownFields(UnknownFieldSet unknownFields);
@@ -136,14 +136,14 @@ namespace Google.ProtocolBuffers {
/// <exception cref="UninitializedMessageException">the message
/// is missing one or more required fields; use BuildPartial to bypass
/// this check</exception>
- new IMessage<T> Build();
+ new T Build();
/// <summary>
/// Like Build(), but does not throw an exception if the message is missing
/// required fields. Instead, a partial message is returned.
/// </summary>
/// <returns></returns>
- new IMessage<T> BuildPartial();
+ new T BuildPartial();
/// <summary>
/// Clones this builder.
@@ -184,7 +184,7 @@ namespace Google.ProtocolBuffers {
/// Get's the message's type's default instance.
/// <see cref="IMessage{T}.DefaultInstanceForType" />
/// </summary>
- new IMessage<T> DefaultInstanceForType { get; }
+ new T DefaultInstanceForType { get; }
/// <summary>
/// Create a builder for messages of the appropriate type for the given field.
diff --git a/csharp/ProtocolBuffers/ProtocolBuffers.csproj b/csharp/ProtocolBuffers/ProtocolBuffers.csproj
index ea30503b..d3cd95f6 100644
--- a/csharp/ProtocolBuffers/ProtocolBuffers.csproj
+++ b/csharp/ProtocolBuffers/ProtocolBuffers.csproj
@@ -48,7 +48,9 @@
<Compile Include="Descriptors\EnumDescriptor.cs" />
<Compile Include="Descriptors\EnumValueDescriptor.cs" />
<Compile Include="Descriptors\FieldDescriptor.cs" />
+ <Compile Include="Descriptors\FieldMappingAttribute.cs" />
<Compile Include="Descriptors\FieldType.cs" />
+ <Compile Include="Descriptors\FileDescriptor.cs" />
<Compile Include="Descriptors\MappedType.cs" />
<Compile Include="Descriptors\MessageDescriptor.cs" />
<Compile Include="ExtensionInfo.cs" />
diff --git a/csharp/ProtocolBuffers/UnknownField.cs b/csharp/ProtocolBuffers/UnknownField.cs
index 1866cbba..e1c12b72 100644
--- a/csharp/ProtocolBuffers/UnknownField.cs
+++ b/csharp/ProtocolBuffers/UnknownField.cs
@@ -24,14 +24,14 @@ namespace Google.ProtocolBuffers {
private static readonly UnknownField defaultInstance = CreateBuilder().Build();
private readonly ReadOnlyCollection<ulong> varintList;
- private readonly ReadOnlyCollection<int> fixed32List;
- private readonly ReadOnlyCollection<long> fixed64List;
+ private readonly ReadOnlyCollection<uint> fixed32List;
+ private readonly ReadOnlyCollection<ulong> fixed64List;
private readonly ReadOnlyCollection<ByteString> lengthDelimitedList;
private readonly ReadOnlyCollection<UnknownFieldSet> groupList;
private UnknownField(ReadOnlyCollection<ulong> varintList,
- ReadOnlyCollection<int> fixed32List,
- ReadOnlyCollection<long> fixed64List,
+ ReadOnlyCollection<uint> fixed32List,
+ ReadOnlyCollection<ulong> fixed64List,
ReadOnlyCollection<ByteString> lengthDelimitedList,
ReadOnlyCollection<UnknownFieldSet> groupList) {
this.varintList = varintList;
@@ -55,14 +55,14 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// The list of fixed32 values for this field.
/// </summary>
- public IList<int> Fixed32List {
+ public IList<uint> Fixed32List {
get { return fixed32List; }
}
/// <summary>
/// The list of fixed64 values for this field.
/// </summary>
- public IList<long> Fixed64List {
+ public IList<ulong> Fixed64List {
get { return fixed64List; }
}
@@ -104,10 +104,10 @@ namespace Google.ProtocolBuffers {
foreach (ulong value in varintList) {
output.WriteUInt64(fieldNumber, value);
}
- foreach (int value in fixed32List) {
+ foreach (uint value in fixed32List) {
output.WriteFixed32(fieldNumber, value);
}
- foreach (long value in fixed64List) {
+ foreach (ulong value in fixed64List) {
output.WriteFixed64(fieldNumber, value);
}
foreach (ByteString value in lengthDelimitedList) {
@@ -172,8 +172,8 @@ namespace Google.ProtocolBuffers {
public class Builder {
private List<ulong> varintList;
- private List<int> fixed32List;
- private List<long> fixed64List;
+ private List<uint> fixed32List;
+ private List<ulong> fixed64List;
private List<ByteString> lengthDelimitedList;
private List<UnknownFieldSet> groupList;
@@ -246,7 +246,7 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Adds a fixed32 value.
/// </summary>
- public Builder AddFixed32(int value) {
+ public Builder AddFixed32(uint value) {
fixed32List = Add(fixed32List, value);
return this;
}
@@ -254,7 +254,7 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Adds a fixed64 value.
/// </summary>
- public Builder AddFixed64(long value) {
+ public Builder AddFixed64(ulong value) {
fixed64List = Add(fixed64List, value);
return this;
}
diff --git a/csharp/ProtocolBuffers/WireFormat.cs b/csharp/ProtocolBuffers/WireFormat.cs
index 0045e369..2166db48 100644
--- a/csharp/ProtocolBuffers/WireFormat.cs
+++ b/csharp/ProtocolBuffers/WireFormat.cs
@@ -13,7 +13,21 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
+using System.Reflection;
+using Google.ProtocolBuffers.Descriptors;
+using System.Collections.Generic;
+using Google.ProtocolBuffers.Collections;
namespace Google.ProtocolBuffers {
+
+ /// <summary>
+ /// This class is used internally by the Protocol Buffer Library and generated
+ /// message implementations. It is public only for the sake of those generated
+ /// messages. Others should not use this class directly.
+ /// <para>
+ /// This class contains constants and helper functions useful for dealing with
+ /// the Protocol Buffer wire format.
+ /// </para>
+ /// </summary>
public class WireFormat {
public enum WireType : uint {
Varint = 0,
@@ -30,6 +44,13 @@ namespace Google.ProtocolBuffers {
internal const int Message = 3;
}
+ internal 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;
@@ -49,9 +70,26 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Makes a tag value given a field number and wire type.
+ /// TODO(jonskeet): Should we just have a Tag structure?
/// </summary>
public static uint MakeTag(int fieldNumber, WireType wireType) {
return (uint) (fieldNumber << TagTypeBits) | (uint) wireType;
}
+
+ /// <summary>
+ /// Immutable mapping from field type to wire type. Built using the attributes on
+ /// FieldType values.
+ /// </summary>
+ public static readonly IDictionary<FieldType, WireType> FieldTypeToWireFormatMap = MapFieldTypes();
+
+ private static IDictionary<FieldType, WireType> MapFieldTypes() {
+ var map = new Dictionary<FieldType, WireType>();
+ foreach (FieldInfo field in typeof(FieldType).GetFields(BindingFlags.Static | BindingFlags.Public)) {
+ FieldType fieldType = (FieldType) field.GetValue(null);
+ FieldMappingAttribute mapping = (FieldMappingAttribute)field.GetCustomAttributes(typeof(FieldMappingAttribute), false)[0];
+ map[fieldType] = mapping.WireType;
+ }
+ return Dictionaries.AsReadOnly(map);
+ }
}
}