First part of dotnet library
committer: Jon Skeet <skeet@pobox.com>
This commit is contained in:
parent
3c38991607
commit
baa2bf54c2
85
csharp/ProtocolBuffers.Test/ByteStringTest.cs
Normal file
85
csharp/ProtocolBuffers.Test/ByteStringTest.cs
Normal file
@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Google.ProtocolBuffers {
|
||||
[TestFixture]
|
||||
public class ByteStringTest {
|
||||
[Test]
|
||||
public void EmptyByteStringHasZeroSize() {
|
||||
Assert.AreEqual(0, ByteString.Empty.Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CopyFromStringWithExplicitEncoding() {
|
||||
ByteString bs = ByteString.CopyFrom("AB", Encoding.Unicode);
|
||||
Assert.AreEqual(4, bs.Length);
|
||||
Assert.AreEqual(65, bs[0]);
|
||||
Assert.AreEqual(0, bs[1]);
|
||||
Assert.AreEqual(66, bs[2]);
|
||||
Assert.AreEqual(0, bs[3]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsEmptyWhenEmpty() {
|
||||
Assert.IsTrue(ByteString.CopyFromUtf8("").IsEmpty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsEmptyWhenNotEmpty() {
|
||||
Assert.IsFalse(ByteString.CopyFromUtf8("X").IsEmpty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CopyFromByteArrayCopiesContents() {
|
||||
byte[] data = new byte[1];
|
||||
data[0] = 10;
|
||||
ByteString bs = ByteString.CopyFrom(data);
|
||||
Assert.AreEqual(10, bs[0]);
|
||||
data[0] = 5;
|
||||
Assert.AreEqual(10, bs[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ToByteArrayCopiesContents() {
|
||||
ByteString bs = ByteString.CopyFromUtf8("Hello");
|
||||
byte[] data = bs.ToByteArray();
|
||||
Assert.AreEqual('H', data[0]);
|
||||
Assert.AreEqual('H', bs[0]);
|
||||
data[0] = 0;
|
||||
Assert.AreEqual(0, data[0]);
|
||||
Assert.AreEqual('H', bs[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CopyFromUtf8UsesUtf8() {
|
||||
ByteString bs = ByteString.CopyFromUtf8("\u20ac");
|
||||
Assert.AreEqual(3, bs.Length);
|
||||
Assert.AreEqual(0xe2, bs[0]);
|
||||
Assert.AreEqual(0x82, bs[1]);
|
||||
Assert.AreEqual(0xac, bs[2]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CopyFromPortion() {
|
||||
byte[] data = new byte[]{0, 1, 2, 3, 4, 5, 6};
|
||||
ByteString bs = ByteString.CopyFrom(data, 2, 3);
|
||||
Assert.AreEqual(3, bs.Length);
|
||||
Assert.AreEqual(2, bs[0]);
|
||||
Assert.AreEqual(3, bs[1]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ToStringUtf8() {
|
||||
ByteString bs = ByteString.CopyFromUtf8("\u20ac");
|
||||
Assert.AreEqual("\u20ac", bs.ToStringUtf8());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ToStringWithExplicitEncoding() {
|
||||
ByteString bs = ByteString.CopyFrom("\u20ac", Encoding.Unicode);
|
||||
Assert.AreEqual("\u20ac", bs.ToString(Encoding.Unicode));
|
||||
}
|
||||
}
|
||||
}
|
36
csharp/ProtocolBuffers.Test/CodedInputStreamTest.cs
Normal file
36
csharp/ProtocolBuffers.Test/CodedInputStreamTest.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Google.ProtocolBuffers {
|
||||
[TestFixture]
|
||||
public class CodedInputStreamTest {
|
||||
|
||||
[Test]
|
||||
public void DecodeZigZag32() {
|
||||
Assert.AreEqual( 0, CodedInputStream.DecodeZigZag32(0));
|
||||
Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(1));
|
||||
Assert.AreEqual( 1, CodedInputStream.DecodeZigZag32(2));
|
||||
Assert.AreEqual(-2, CodedInputStream.DecodeZigZag32(3));
|
||||
Assert.AreEqual(0x3FFFFFFF, CodedInputStream.DecodeZigZag32(0x7FFFFFFE));
|
||||
Assert.AreEqual(unchecked((int)0xC0000000), CodedInputStream.DecodeZigZag32(0x7FFFFFFF));
|
||||
Assert.AreEqual(0x7FFFFFFF, CodedInputStream.DecodeZigZag32(0xFFFFFFFE));
|
||||
Assert.AreEqual(unchecked((int)0x80000000), CodedInputStream.DecodeZigZag32(0xFFFFFFFF));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DecodeZigZag64() {
|
||||
Assert.AreEqual( 0, CodedInputStream.DecodeZigZag64(0));
|
||||
Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(1));
|
||||
Assert.AreEqual( 1, CodedInputStream.DecodeZigZag64(2));
|
||||
Assert.AreEqual(-2, CodedInputStream.DecodeZigZag64(3));
|
||||
Assert.AreEqual(0x000000003FFFFFFFL, CodedInputStream.DecodeZigZag64(0x000000007FFFFFFEL));
|
||||
Assert.AreEqual(unchecked((long)0xFFFFFFFFC0000000L), CodedInputStream.DecodeZigZag64(0x000000007FFFFFFFL));
|
||||
Assert.AreEqual(0x000000007FFFFFFFL, CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFEL));
|
||||
Assert.AreEqual(unchecked((long)0xFFFFFFFF80000000L), CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFFL));
|
||||
Assert.AreEqual(0x7FFFFFFFFFFFFFFFL, CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFEL));
|
||||
Assert.AreEqual(unchecked((long)0x8000000000000000L),CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFFL));
|
||||
}
|
||||
}
|
||||
}
|
237
csharp/ProtocolBuffers.Test/CodedOutputStreamTest.cs
Normal file
237
csharp/ProtocolBuffers.Test/CodedOutputStreamTest.cs
Normal file
@ -0,0 +1,237 @@
|
||||
using NUnit.Framework;
|
||||
using System.IO;
|
||||
|
||||
namespace Google.ProtocolBuffers {
|
||||
[TestFixture]
|
||||
public class CodedOutputStreamTest {
|
||||
|
||||
/// <summary>
|
||||
/// Helper to construct a byte array from a bunch of bytes. The inputs are
|
||||
/// actually ints so that I can use hex notation and not get stupid errors
|
||||
/// about precision.
|
||||
/// </summary>
|
||||
private static byte[] Bytes(params int[] bytesAsInts) {
|
||||
byte[] bytes = new byte[bytesAsInts.Length];
|
||||
for (int i = 0; i < bytesAsInts.Length; i++) {
|
||||
bytes[i] = (byte) bytesAsInts[i];
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the given value using WriteRawVarint32() and WriteRawVarint64() and
|
||||
/// checks that the result matches the given bytes
|
||||
/// </summary>
|
||||
private static void AssertWriteVarint(byte[] data, ulong value) {
|
||||
// Only do 32-bit write if the value fits in 32 bits.
|
||||
if ((value >> 32) == 0) {
|
||||
MemoryStream rawOutput = new MemoryStream();
|
||||
CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
|
||||
output.WriteRawVarint32((uint) value);
|
||||
output.Flush();
|
||||
Assert.AreEqual(data, rawOutput.ToArray());
|
||||
// Also try computing size.
|
||||
Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint32Size((uint) value));
|
||||
}
|
||||
|
||||
{
|
||||
MemoryStream rawOutput = new MemoryStream();
|
||||
CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
|
||||
output.WriteRawVarint64(value);
|
||||
output.Flush();
|
||||
Assert.AreEqual(data, rawOutput.ToArray());
|
||||
|
||||
// Also try computing size.
|
||||
Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint64Size(value));
|
||||
}
|
||||
|
||||
// Try different buffer sizes.
|
||||
for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2) {
|
||||
// Only do 32-bit write if the value fits in 32 bits.
|
||||
if ((value >> 32) == 0) {
|
||||
MemoryStream rawOutput = new MemoryStream();
|
||||
CodedOutputStream output =
|
||||
CodedOutputStream.CreateInstance(rawOutput, bufferSize);
|
||||
output.WriteRawVarint32((uint) value);
|
||||
output.Flush();
|
||||
Assert.AreEqual(data, rawOutput.ToArray());
|
||||
}
|
||||
|
||||
{
|
||||
MemoryStream rawOutput = new MemoryStream();
|
||||
CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput, bufferSize);
|
||||
output.WriteRawVarint64(value);
|
||||
output.Flush();
|
||||
Assert.AreEqual(data, rawOutput.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests WriteRawVarint32() and WriteRawVarint64()
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void WriteVarint() {
|
||||
AssertWriteVarint(Bytes(0x00), 0);
|
||||
AssertWriteVarint(Bytes(0x01), 1);
|
||||
AssertWriteVarint(Bytes(0x7f), 127);
|
||||
// 14882
|
||||
AssertWriteVarint(Bytes(0xa2, 0x74), (0x22 << 0) | (0x74 << 7));
|
||||
// 2961488830
|
||||
AssertWriteVarint(Bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b),
|
||||
(0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
|
||||
(0x0bL << 28));
|
||||
|
||||
// 64-bit
|
||||
// 7256456126
|
||||
AssertWriteVarint(Bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b),
|
||||
(0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
|
||||
(0x1bL << 28));
|
||||
// 41256202580718336
|
||||
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));
|
||||
// 11964378330978735131
|
||||
AssertWriteVarint(
|
||||
Bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01),
|
||||
unchecked((ulong)
|
||||
((0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
|
||||
(0x3bL << 28) | (0x56L << 35) | (0x00L << 42) |
|
||||
(0x05L << 49) | (0x26L << 56) | (0x01L << 63))));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the given bytes using WriteRawLittleEndian32() and checks
|
||||
/// that the result matches the given value.
|
||||
/// </summary>
|
||||
private static void AssertWriteLittleEndian32(byte[] data, int value) {
|
||||
MemoryStream rawOutput = new MemoryStream();
|
||||
CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
|
||||
output.WriteRawLittleEndian32(value);
|
||||
output.Flush();
|
||||
Assert.AreEqual(data, rawOutput.ToArray());
|
||||
|
||||
// Try different buffer sizes.
|
||||
for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2) {
|
||||
rawOutput = new MemoryStream();
|
||||
output = CodedOutputStream.CreateInstance(rawOutput, bufferSize);
|
||||
output.WriteRawLittleEndian32(value);
|
||||
output.Flush();
|
||||
Assert.AreEqual(data, rawOutput.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the given bytes using WriteRawLittleEndian64() and checks
|
||||
/// that the result matches the given value.
|
||||
/// </summary>
|
||||
private static void AssertWriteLittleEndian64(byte[] data, long value) {
|
||||
MemoryStream rawOutput = new MemoryStream();
|
||||
CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
|
||||
output.WriteRawLittleEndian64(value);
|
||||
output.Flush();
|
||||
Assert.AreEqual(data, rawOutput.ToArray());
|
||||
|
||||
// Try different block sizes.
|
||||
for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
|
||||
rawOutput = new MemoryStream();
|
||||
output = CodedOutputStream.CreateInstance(rawOutput, blockSize);
|
||||
output.WriteRawLittleEndian64(value);
|
||||
output.Flush();
|
||||
Assert.AreEqual(data, rawOutput.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests writeRawLittleEndian32() and writeRawLittleEndian64().
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void WriteLittleEndian() {
|
||||
AssertWriteLittleEndian32(Bytes(0x78, 0x56, 0x34, 0x12), 0x12345678);
|
||||
AssertWriteLittleEndian32(Bytes(0xf0, 0xde, 0xbc, 0x9a), unchecked((int)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));
|
||||
}
|
||||
|
||||
/* TODO(jonskeet): Put this back when we've got the rest working!
|
||||
[Test]
|
||||
public void testWriteWholeMessage() throws Exception {
|
||||
TestAllTypes message = TestUtil.getAllSet();
|
||||
|
||||
byte[] rawBytes = message.toByteArray();
|
||||
assertEqualBytes(TestUtil.getGoldenMessage().toByteArray(), rawBytes);
|
||||
|
||||
// Try different block sizes.
|
||||
for (int blockSize = 1; blockSize < 256; blockSize *= 2) {
|
||||
MemoryStream rawOutput = new MemoryStream();
|
||||
CodedOutputStream output =
|
||||
CodedOutputStream.newInstance(rawOutput, blockSize);
|
||||
message.writeTo(output);
|
||||
output.flush();
|
||||
assertEqualBytes(rawBytes, rawOutput.toByteArray());
|
||||
}
|
||||
} */
|
||||
|
||||
|
||||
[Test]
|
||||
public void EncodeZigZag32() {
|
||||
Assert.AreEqual(0, CodedOutputStream.EncodeZigZag32( 0));
|
||||
Assert.AreEqual(1, CodedOutputStream.EncodeZigZag32(-1));
|
||||
Assert.AreEqual(2, CodedOutputStream.EncodeZigZag32( 1));
|
||||
Assert.AreEqual(3, CodedOutputStream.EncodeZigZag32(-2));
|
||||
Assert.AreEqual(0x7FFFFFFE, CodedOutputStream.EncodeZigZag32(0x3FFFFFFF));
|
||||
Assert.AreEqual(0x7FFFFFFF, CodedOutputStream.EncodeZigZag32(unchecked((int)0xC0000000)));
|
||||
Assert.AreEqual(0xFFFFFFFE, CodedOutputStream.EncodeZigZag32(0x7FFFFFFF));
|
||||
Assert.AreEqual(0xFFFFFFFF, CodedOutputStream.EncodeZigZag32(unchecked((int)0x80000000)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EncodeZigZag64() {
|
||||
Assert.AreEqual(0, CodedOutputStream.EncodeZigZag64( 0));
|
||||
Assert.AreEqual(1, CodedOutputStream.EncodeZigZag64(-1));
|
||||
Assert.AreEqual(2, CodedOutputStream.EncodeZigZag64( 1));
|
||||
Assert.AreEqual(3, CodedOutputStream.EncodeZigZag64(-2));
|
||||
Assert.AreEqual(0x000000007FFFFFFEL,
|
||||
CodedOutputStream.EncodeZigZag64(unchecked((long)0x000000003FFFFFFFUL)));
|
||||
Assert.AreEqual(0x000000007FFFFFFFL,
|
||||
CodedOutputStream.EncodeZigZag64(unchecked((long)0xFFFFFFFFC0000000UL)));
|
||||
Assert.AreEqual(0x00000000FFFFFFFEL,
|
||||
CodedOutputStream.EncodeZigZag64(unchecked((long)0x000000007FFFFFFFUL)));
|
||||
Assert.AreEqual(0x00000000FFFFFFFFL,
|
||||
CodedOutputStream.EncodeZigZag64(unchecked((long)0xFFFFFFFF80000000UL)));
|
||||
Assert.AreEqual(0xFFFFFFFFFFFFFFFEL,
|
||||
CodedOutputStream.EncodeZigZag64(unchecked((long)0x7FFFFFFFFFFFFFFFUL)));
|
||||
Assert.AreEqual(0xFFFFFFFFFFFFFFFFL,
|
||||
CodedOutputStream.EncodeZigZag64(unchecked((long)0x8000000000000000UL)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RoundTripZigZag32() {
|
||||
// Some easier-to-verify round-trip tests. The inputs (other than 0, 1, -1)
|
||||
// were chosen semi-randomly via keyboard bashing.
|
||||
Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(0)));
|
||||
Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(1)));
|
||||
Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-1)));
|
||||
Assert.AreEqual(14927, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(14927)));
|
||||
Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-3612)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RoundTripZigZag64() {
|
||||
Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(0)));
|
||||
Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(1)));
|
||||
Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-1)));
|
||||
Assert.AreEqual(14927, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(14927)));
|
||||
Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-3612)));
|
||||
|
||||
Assert.AreEqual(856912304801416L, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(856912304801416L)));
|
||||
Assert.AreEqual(-75123905439571256L, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-75123905439571256L)));
|
||||
}
|
||||
}
|
||||
}
|
36
csharp/ProtocolBuffers.Test/Properties/AssemblyInfo.cs
Normal file
36
csharp/ProtocolBuffers.Test/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("ProtocolBuffers.Test")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("ProtocolBuffers.Test")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2008")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("54e627c3-daaa-4850-82cf-f25b7f097e78")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
66
csharp/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
Normal file
66
csharp/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
Normal file
@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.21022</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{DD01ED24-3750-4567-9A23-1DB676A15610}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Google.ProtocolBuffers</RootNamespace>
|
||||
<AssemblyName>Google.ProtocolBuffers.Test</AssemblyName>
|
||||
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="nunit.framework, Version=2.2.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>lib\nunit.framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Rhino.Mocks, Version=3.5.0.2, Culture=neutral, PublicKeyToken=0b3305902db7183f, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>lib\Rhino.Mocks.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ByteStringTest.cs" />
|
||||
<Compile Include="CodedInputStreamTest.cs" />
|
||||
<Compile Include="CodedOutputStreamTest.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ProtocolBuffers\ProtocolBuffers.csproj">
|
||||
<Project>{6908BDCE-D925-43F3-94AC-A531E6DF2591}</Project>
|
||||
<Name>ProtocolBuffers</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
BIN
csharp/ProtocolBuffers.Test/lib/Rhino.Mocks.dll
Normal file
BIN
csharp/ProtocolBuffers.Test/lib/Rhino.Mocks.dll
Normal file
Binary file not shown.
5062
csharp/ProtocolBuffers.Test/lib/Rhino.Mocks.xml
Normal file
5062
csharp/ProtocolBuffers.Test/lib/Rhino.Mocks.xml
Normal file
File diff suppressed because it is too large
Load Diff
BIN
csharp/ProtocolBuffers.Test/lib/nunit.framework.dll
Normal file
BIN
csharp/ProtocolBuffers.Test/lib/nunit.framework.dll
Normal file
Binary file not shown.
96
csharp/ProtocolBuffers/ByteString.cs
Normal file
96
csharp/ProtocolBuffers/ByteString.cs
Normal file
@ -0,0 +1,96 @@
|
||||
using System.Text;
|
||||
using System;
|
||||
|
||||
namespace Google.ProtocolBuffers {
|
||||
/// <summary>
|
||||
/// Immutable array of bytes.
|
||||
/// TODO(jonskeet): Implement the common collection interfaces?
|
||||
/// </summary>
|
||||
public sealed class ByteString {
|
||||
|
||||
private static readonly ByteString empty = new ByteString(new byte[0]);
|
||||
|
||||
private byte[] bytes;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new ByteString from the given byte array. The array is
|
||||
/// *not* copied, and must not be modified after this constructor is called.
|
||||
/// </summary>
|
||||
private ByteString(byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an empty ByteString.
|
||||
/// </summary>
|
||||
public static ByteString Empty {
|
||||
get { return empty; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the length of this ByteString in bytes.
|
||||
/// </summary>
|
||||
public int Length {
|
||||
get { return bytes.Length; }
|
||||
}
|
||||
|
||||
public bool IsEmpty {
|
||||
get { return Length == 0; }
|
||||
}
|
||||
|
||||
public byte[] ToByteArray() {
|
||||
return (byte[])bytes.Clone();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a ByteString from the given array. The contents
|
||||
/// are copied, so further modifications to the array will not
|
||||
/// be reflected in the returned ByteString.
|
||||
/// </summary>
|
||||
public static ByteString CopyFrom(byte[] bytes) {
|
||||
return new ByteString((byte[]) bytes.Clone());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a ByteString from a portion of a byte array.
|
||||
/// </summary>
|
||||
public static ByteString CopyFrom(byte[] bytes, int offset, int count) {
|
||||
byte[] portion = new byte[count];
|
||||
Array.Copy(bytes, offset, portion, 0, count);
|
||||
return new ByteString(portion);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new ByteString by encoding the specified text with
|
||||
/// the given encoding.
|
||||
/// </summary>
|
||||
public static ByteString CopyFrom(string text, Encoding encoding) {
|
||||
return new ByteString(encoding.GetBytes(text));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new ByteString by encoding the specified text in UTF-8.
|
||||
/// </summary>
|
||||
public static ByteString CopyFromUtf8(string text) {
|
||||
return CopyFrom(text, Encoding.UTF8);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retuns the byte at the given index.
|
||||
/// </summary>
|
||||
public byte this[int index] {
|
||||
get { return bytes[index]; }
|
||||
}
|
||||
|
||||
public string ToString(Encoding encoding) {
|
||||
return encoding.GetString(bytes);
|
||||
}
|
||||
|
||||
public string ToStringUtf8() {
|
||||
return ToString(Encoding.UTF8);
|
||||
}
|
||||
|
||||
// TODO(jonskeet): CopyTo, Equals, GetHashCode if they turn out to be required
|
||||
// TODO(jonskeet): Input/Output stuff
|
||||
}
|
||||
}
|
31
csharp/ProtocolBuffers/CodedInputStream.cs
Normal file
31
csharp/ProtocolBuffers/CodedInputStream.cs
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
namespace Google.ProtocolBuffers {
|
||||
public sealed class CodedInputStream {
|
||||
|
||||
/// <summary>
|
||||
/// Decode a 32-bit value with ZigZag encoding.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// ZigZag encodes signed integers into values that can be efficiently
|
||||
/// encoded with varint. (Otherwise, negative values must be
|
||||
/// sign-extended to 64 bits to be varint encoded, thus always taking
|
||||
/// 10 bytes on the wire.)
|
||||
/// </remarks>
|
||||
public static int DecodeZigZag32(uint n) {
|
||||
return (int)(n >> 1) ^ -(int)(n & 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decode a 32-bit value with ZigZag encoding.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// ZigZag encodes signed integers into values that can be efficiently
|
||||
/// encoded with varint. (Otherwise, negative values must be
|
||||
/// sign-extended to 64 bits to be varint encoded, thus always taking
|
||||
/// 10 bytes on the wire.)
|
||||
/// </remarks>
|
||||
public static long DecodeZigZag64(ulong n) {
|
||||
return (long)(n >> 1) ^ -(long)(n & 1);
|
||||
}
|
||||
}
|
||||
}
|
708
csharp/ProtocolBuffers/CodedOutputStream.cs
Normal file
708
csharp/ProtocolBuffers/CodedOutputStream.cs
Normal file
@ -0,0 +1,708 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// 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;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace Google.ProtocolBuffers {
|
||||
|
||||
/// <summary>
|
||||
/// Encodes and writes protocol message fields.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class contains two kinds of methods: methods that write specific
|
||||
/// protocol message constructs and field types (e.g. WriteTag and
|
||||
/// WriteInt32) and methods that write low-level values (e.g.
|
||||
/// WriteRawVarint32 and WriteRawBytes). If you are writing encoded protocol
|
||||
/// messages, you should use the former methods, but if you are writing some
|
||||
/// other format of your own design, use the latter. The names of the former
|
||||
/// methods are taken from the protocol buffer type names, not .NET types.
|
||||
/// (Hence WriteFloat instead of WriteSingle, and WriteBool instead of WriteBoolean.)
|
||||
/// </remarks>
|
||||
public sealed class CodedOutputStream {
|
||||
/// <summary>
|
||||
/// The buffer size used by CreateInstance(Stream).
|
||||
/// </summary>
|
||||
public static readonly int DefaultBufferSize = 4096;
|
||||
|
||||
private readonly byte[] buffer;
|
||||
private readonly int limit;
|
||||
private int position;
|
||||
private readonly Stream output;
|
||||
|
||||
#region Construction
|
||||
private CodedOutputStream(byte[] buffer, int offset, int length) {
|
||||
this.output = null;
|
||||
this.buffer = buffer;
|
||||
this.position = offset;
|
||||
this.limit = offset + length;
|
||||
}
|
||||
|
||||
private CodedOutputStream(Stream output, byte[] buffer) {
|
||||
this.output = output;
|
||||
this.buffer = buffer;
|
||||
this.position = 0;
|
||||
this.limit = buffer.Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new CodedOutputStream which write to the given stream.
|
||||
/// </summary>
|
||||
public static CodedOutputStream CreateInstance(Stream output) {
|
||||
return CreateInstance(output, DefaultBufferSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new CodedOutputStream which write to the given stream and uses
|
||||
/// the specified buffer size.
|
||||
/// </summary>
|
||||
public static CodedOutputStream CreateInstance(Stream output, int bufferSize) {
|
||||
return new CodedOutputStream(output, new byte[bufferSize]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new CodedOutputStream that writes directly to the given
|
||||
/// byte array. If more bytes are written than fit in the array,
|
||||
/// OutOfSpaceException will be thrown.
|
||||
/// </summary>
|
||||
public static CodedOutputStream CreateInstance(byte[] flatArray) {
|
||||
return CreateInstance(flatArray, 0, flatArray.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new CodedOutputStream that writes directly to the given
|
||||
/// byte array slice. If more bytes are written than fit in the array,
|
||||
/// OutOfSpaceException will be thrown.
|
||||
/// </summary>
|
||||
public static CodedOutputStream CreateInstance(byte[] flatArray, int offset, int length) {
|
||||
return new CodedOutputStream(flatArray, offset, length);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Writing of tags etc
|
||||
/// <summary>
|
||||
/// Writes a double field value, including tag, to the stream.
|
||||
/// </summary>
|
||||
public void WriteDouble(int fieldNumber, double value) {
|
||||
WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
|
||||
WriteRawLittleEndian64(BitConverter.DoubleToInt64Bits(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a float field value, including tag, to the stream.
|
||||
/// </summary>
|
||||
public void WriteFloat(int fieldNumber, float value) {
|
||||
WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
|
||||
// FIXME: How do we convert a single to 32 bits? (Without unsafe code)
|
||||
//WriteRawLittleEndian32(BitConverter.SingleT(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a uint64 field value, including tag, to the stream.
|
||||
/// </summary>
|
||||
public void WriteUInt64(int fieldNumber, ulong value) {
|
||||
WriteTag(fieldNumber, WireFormat.WireType.Varint);
|
||||
WriteRawVarint64(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an int64 field value, including tag, to the stream.
|
||||
/// </summary>
|
||||
public void WriteInt64(int fieldNumber, long value) {
|
||||
WriteTag(fieldNumber, WireFormat.WireType.Varint);
|
||||
WriteRawVarint64((ulong)value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an int32 field value, including tag, to the stream.
|
||||
/// </summary>
|
||||
public void WriteInt32(int fieldNumber, int value) {
|
||||
WriteTag(fieldNumber, WireFormat.WireType.Varint);
|
||||
if (value >= 0) {
|
||||
WriteRawVarint32((uint)value);
|
||||
} else {
|
||||
// Must sign-extend.
|
||||
WriteRawVarint64((ulong)value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a fixed64 field value, including tag, to the stream.
|
||||
/// </summary>
|
||||
public void WriteFixed64(int fieldNumber, long value) {
|
||||
WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
|
||||
WriteRawLittleEndian64(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a fixed32 field value, including tag, to the stream.
|
||||
/// </summary>
|
||||
public void WriteFixed32(int fieldNumber, int value) {
|
||||
WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
|
||||
WriteRawLittleEndian32(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a bool field value, including tag, to the stream.
|
||||
/// </summary>
|
||||
public void WriteBool(int fieldNumber, bool value) {
|
||||
WriteTag(fieldNumber, WireFormat.WireType.Varint);
|
||||
WriteRawByte(value ? (byte)1 : (byte)0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a string field value, including tag, to the stream.
|
||||
/// </summary>
|
||||
public void WriteString(int fieldNumber, string value) {
|
||||
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
|
||||
// TODO(jonskeet): Optimise this if possible
|
||||
// Unfortunately there does not appear to be any way to tell Java to encode
|
||||
// UTF-8 directly into our buffer, so we have to let it create its own byte
|
||||
// array and then copy. In .NET we can do the same thing very easily,
|
||||
// so we don't need to worry about only writing one buffer at a time.
|
||||
// We can optimise later.
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(value);
|
||||
WriteRawVarint32((uint)bytes.Length);
|
||||
WriteRawBytes(bytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a group field value, including tag, to the stream.
|
||||
/// </summary>
|
||||
public void WriteGroup(int fieldNumber, IMessage value) {
|
||||
WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
|
||||
value.WriteTo(this);
|
||||
WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
|
||||
}
|
||||
|
||||
public void WriteUnknownGroup(int fieldNumber, UnknownFieldSet value) {
|
||||
WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
|
||||
value.WriteTo(this);
|
||||
WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
|
||||
}
|
||||
|
||||
public void WriteMessage(int fieldNumber, IMessage value) {
|
||||
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
|
||||
WriteRawVarint32((uint)value.SerializedSize);
|
||||
value.WriteTo(this);
|
||||
}
|
||||
|
||||
public void WriteBytes(int fieldNumber, ByteString value) {
|
||||
// TODO(jonskeet): Optimise this! (No need to copy the bytes twice.)
|
||||
byte[] bytes = value.ToByteArray();
|
||||
WriteRawVarint32((uint)bytes.Length);
|
||||
WriteRawBytes(bytes);
|
||||
}
|
||||
|
||||
public void WriteUInt32(int fieldNumber, uint value) {
|
||||
WriteTag(fieldNumber, WireFormat.WireType.Varint);
|
||||
WriteRawVarint32(value);
|
||||
}
|
||||
|
||||
public void WriteEnum(int fieldNumber, int value) {
|
||||
WriteTag(fieldNumber, WireFormat.WireType.Varint);
|
||||
WriteRawVarint32((uint)value);
|
||||
}
|
||||
|
||||
public void WriteSFixed32(int fieldNumber, int value) {
|
||||
WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
|
||||
WriteRawVarint32((uint)value);
|
||||
}
|
||||
|
||||
public void WriteSFixed64(int fieldNumber, long value) {
|
||||
WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
|
||||
WriteRawVarint64((ulong)value);
|
||||
}
|
||||
|
||||
public void WriteSInt32(int fieldNumber, int value) {
|
||||
WriteTag(fieldNumber, WireFormat.WireType.Varint);
|
||||
WriteRawVarint32(EncodeZigZag32(value));
|
||||
}
|
||||
|
||||
public void WriteSInt64(int fieldNumber, long value) {
|
||||
WriteTag(fieldNumber, WireFormat.WireType.Varint);
|
||||
WriteRawVarint64(EncodeZigZag64(value));
|
||||
}
|
||||
|
||||
public void WriteMessageSetExtension(int fieldNumber, IMessage value) {
|
||||
WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup);
|
||||
WriteUInt32(WireFormat.MessageSetField.TypeID, (uint)fieldNumber);
|
||||
WriteMessage(WireFormat.MessageSetField.Message, value);
|
||||
WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup);
|
||||
}
|
||||
|
||||
public void WriteRawMessageSetExtension(int fieldNumber, ByteString value) {
|
||||
WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup);
|
||||
WriteUInt32(WireFormat.MessageSetField.TypeID, (uint)fieldNumber);
|
||||
WriteBytes(WireFormat.MessageSetField.Message, value);
|
||||
WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup);
|
||||
}
|
||||
|
||||
public void WriteField(Descriptors.FieldDescriptor.Type fieldType, int fieldNumber, object value) {
|
||||
switch (fieldType) {
|
||||
case Descriptors.FieldDescriptor.Type.Double: WriteDouble(fieldNumber, (double)value); break;
|
||||
case Descriptors.FieldDescriptor.Type.Float: WriteFloat(fieldNumber, (float)value); break;
|
||||
case Descriptors.FieldDescriptor.Type.Int64: WriteInt64(fieldNumber, (long)value); break;
|
||||
case Descriptors.FieldDescriptor.Type.UInt64: WriteUInt64(fieldNumber, (ulong)value); break;
|
||||
case Descriptors.FieldDescriptor.Type.Int32: WriteInt32(fieldNumber, (int)value); break;
|
||||
case Descriptors.FieldDescriptor.Type.Fixed64: WriteFixed64(fieldNumber, (long)value); break;
|
||||
case Descriptors.FieldDescriptor.Type.Fixed32: WriteFixed32(fieldNumber, (int)value); break;
|
||||
case Descriptors.FieldDescriptor.Type.Bool: WriteBool(fieldNumber, (bool)value); break;
|
||||
case Descriptors.FieldDescriptor.Type.String: WriteString(fieldNumber, (string)value); break;
|
||||
case Descriptors.FieldDescriptor.Type.Group: WriteGroup(fieldNumber, (IMessage)value); break;
|
||||
case Descriptors.FieldDescriptor.Type.Message: WriteMessage(fieldNumber, (IMessage)value); break;
|
||||
case Descriptors.FieldDescriptor.Type.Bytes: WriteBytes(fieldNumber, (ByteString)value); break;
|
||||
case Descriptors.FieldDescriptor.Type.UInt32: WriteUInt32(fieldNumber, (uint)value); break;
|
||||
case Descriptors.FieldDescriptor.Type.SFixed32: WriteSFixed32(fieldNumber, (int)value); break;
|
||||
case Descriptors.FieldDescriptor.Type.SFixed64: WriteSFixed64(fieldNumber, (long)value); break;
|
||||
case Descriptors.FieldDescriptor.Type.SInt32: WriteSInt32(fieldNumber, (int)value); break;
|
||||
case Descriptors.FieldDescriptor.Type.SInt64: WriteSInt64(fieldNumber, (long)value); break;
|
||||
case Descriptors.FieldDescriptor.Type.Enum: WriteEnum(fieldNumber, ((Descriptors.EnumValueDescriptor)value).Number);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Underlying writing primitives
|
||||
/// <summary>
|
||||
/// Encodes and writes a tag.
|
||||
/// </summary>
|
||||
public void WriteTag(int fieldNumber, WireFormat.WireType type) {
|
||||
WriteRawVarint32(WireFormat.MakeTag(fieldNumber, type));
|
||||
}
|
||||
|
||||
public void WriteRawVarint32(uint value) {
|
||||
while (true) {
|
||||
if ((value & ~0x7F) == 0) {
|
||||
WriteRawByte(value);
|
||||
return;
|
||||
} else {
|
||||
WriteRawByte((value & 0x7F) | 0x80);
|
||||
value >>= 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteRawVarint64(ulong value) {
|
||||
while (true) {
|
||||
if ((value & ~0x7FUL) == 0) {
|
||||
WriteRawByte((uint)value);
|
||||
return;
|
||||
} else {
|
||||
WriteRawByte(((uint)value & 0x7F) | 0x80);
|
||||
value >>= 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteRawLittleEndian32(int value) {
|
||||
WriteRawByte((byte)value);
|
||||
WriteRawByte((byte)(value >> 8));
|
||||
WriteRawByte((byte)(value >> 16));
|
||||
WriteRawByte((byte)(value >> 24));
|
||||
}
|
||||
|
||||
public void WriteRawLittleEndian64(long value) {
|
||||
WriteRawByte((byte)value);
|
||||
WriteRawByte((byte)(value >> 8));
|
||||
WriteRawByte((byte)(value >> 16));
|
||||
WriteRawByte((byte)(value >> 24));
|
||||
WriteRawByte((byte)(value >> 32));
|
||||
WriteRawByte((byte)(value >> 40));
|
||||
WriteRawByte((byte)(value >> 48));
|
||||
WriteRawByte((byte)(value >> 56));
|
||||
}
|
||||
|
||||
public void WriteRawByte(byte value) {
|
||||
if (position == limit) {
|
||||
RefreshBuffer();
|
||||
}
|
||||
|
||||
buffer[position++] = value;
|
||||
}
|
||||
|
||||
public void WriteRawByte(uint value) {
|
||||
WriteRawByte((byte)value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes out an array of bytes.
|
||||
/// </summary>
|
||||
public void WriteRawBytes(byte[] value) {
|
||||
WriteRawBytes(value, 0, value.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes out part of an array of bytes.
|
||||
/// </summary>
|
||||
public void WriteRawBytes(byte[] value, int offset, int length) {
|
||||
if (limit - position >= length) {
|
||||
Array.Copy(value, offset, buffer, position, length);
|
||||
// We have room in the current buffer.
|
||||
position += length;
|
||||
} else {
|
||||
// Write extends past current buffer. Fill the rest of this buffer and
|
||||
// flush.
|
||||
int bytesWritten = limit - position;
|
||||
Array.Copy(value, offset, buffer, position, bytesWritten);
|
||||
offset += bytesWritten;
|
||||
length -= bytesWritten;
|
||||
position = limit;
|
||||
RefreshBuffer();
|
||||
|
||||
// Now deal with the rest.
|
||||
// Since we have an output stream, this is our buffer
|
||||
// and buffer offset == 0
|
||||
if (length <= limit) {
|
||||
// Fits in new buffer.
|
||||
Array.Copy(value, offset, buffer, 0, length);
|
||||
position = length;
|
||||
} else {
|
||||
// Write is very big. Let's do it all at once.
|
||||
output.Write(value, offset, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Size computations
|
||||
|
||||
const int LittleEndian64Size = 8;
|
||||
const int LittleEndian32Size = 4;
|
||||
|
||||
/// <summary>
|
||||
/// Compute the number of bytes that would be needed to encode a
|
||||
/// double field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeDoubleSize(int fieldNumber, double value) {
|
||||
return ComputeTagSize(fieldNumber) + LittleEndian64Size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the number of bytes that would be needed to encode a
|
||||
/// float field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeFloatSize(int fieldNumber, float value) {
|
||||
return ComputeTagSize(fieldNumber) + LittleEndian32Size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the number of bytes that would be needed to encode a
|
||||
/// uint64 field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeUInt64Size(int fieldNumber, ulong value) {
|
||||
return ComputeTagSize(fieldNumber) + ComputeRawVarint64Size(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the number of bytes that would be needed to encode an
|
||||
/// int64 field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeInt64Size(int fieldNumber, long value) {
|
||||
return ComputeTagSize(fieldNumber) + ComputeRawVarint64Size((ulong)value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the number of bytes that would be needed to encode an
|
||||
/// int32 field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeInt32Size(int fieldNumber, int value) {
|
||||
if (value >= 0) {
|
||||
return ComputeTagSize(fieldNumber) + ComputeRawVarint32Size((uint)value);
|
||||
} else {
|
||||
// Must sign-extend.
|
||||
return ComputeTagSize(fieldNumber) + 10;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the number of bytes that would be needed to encode a
|
||||
/// fixed64 field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeFixed64Size(int fieldNumber, long value) {
|
||||
return ComputeTagSize(fieldNumber) + LittleEndian64Size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the number of bytes that would be needed to encode a
|
||||
/// fixed32 field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeFixed32Size(int fieldNumber, int value) {
|
||||
return ComputeTagSize(fieldNumber) + LittleEndian32Size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the number of bytes that would be needed to encode a
|
||||
/// bool field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeBoolSize(int fieldNumber, bool value) {
|
||||
return ComputeTagSize(fieldNumber) + 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the number of bytes that would be needed to encode a
|
||||
/// string field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeStringSize(int fieldNumber, String value) {
|
||||
int byteArraySize = Encoding.UTF8.GetByteCount(value);
|
||||
return ComputeTagSize(fieldNumber) +
|
||||
ComputeRawVarint32Size((uint)byteArraySize) +
|
||||
byteArraySize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the number of bytes that would be needed to encode a
|
||||
/// group field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeGroupSize(int fieldNumber, IMessage value) {
|
||||
return ComputeTagSize(fieldNumber) * 2 + value.SerializedSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the number of bytes that would be needed to encode a
|
||||
/// group field represented by an UnknownFieldSet, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeUnknownGroupSize(int fieldNumber,
|
||||
UnknownFieldSet value) {
|
||||
return ComputeTagSize(fieldNumber) * 2 + value.SerializedSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the number of bytes that would be needed to encode an
|
||||
/// embedded message field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeMessageSize(int fieldNumber, IMessage value) {
|
||||
int size = value.SerializedSize;
|
||||
return ComputeTagSize(fieldNumber) + ComputeRawVarint32Size((uint)size) + size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the number of bytes that would be needed to encode a
|
||||
/// bytes field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeBytesSize(int fieldNumber, ByteString value) {
|
||||
return ComputeTagSize(fieldNumber) +
|
||||
ComputeRawVarint32Size((uint)value.Length) +
|
||||
value.Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the number of bytes that would be needed to encode a
|
||||
/// uint32 field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeUInt32Size(int fieldNumber, uint value) {
|
||||
return ComputeTagSize(fieldNumber) + ComputeRawVarint32Size(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the number of bytes that would be needed to encode a
|
||||
/// enum field, including the tag. The caller is responsible for
|
||||
/// converting the enum value to its numeric value.
|
||||
/// </summary>
|
||||
public static int ComputeEnumSize(int fieldNumber, int value) {
|
||||
return ComputeTagSize(fieldNumber) + ComputeRawVarint32Size((uint)value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the number of bytes that would be needed to encode an
|
||||
/// sfixed32 field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeSFixed32Size(int fieldNumber, int value) {
|
||||
return ComputeTagSize(fieldNumber) + LittleEndian32Size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the number of bytes that would be needed to encode an
|
||||
/// sfixed64 field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeSFixed64Size(int fieldNumber, long value) {
|
||||
return ComputeTagSize(fieldNumber) + LittleEndian64Size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the number of bytes that would be needed to encode an
|
||||
/// sint32 field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeSInt32Size(int fieldNumber, int value) {
|
||||
return ComputeTagSize(fieldNumber) +
|
||||
ComputeRawVarint32Size(EncodeZigZag32(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the number of bytes that would be needed to encode an
|
||||
/// sint64 field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeSInt64Size(int fieldNumber, long value) {
|
||||
return ComputeTagSize(fieldNumber) +
|
||||
ComputeRawVarint64Size(EncodeZigZag64(value));
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* MessageSet extension to the stream. For historical reasons,
|
||||
* the wire format differs from normal fields.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Compute the number of bytes that would be needed to encode a
|
||||
/// MessageSet extension to the stream. For historical reasons,
|
||||
/// the wire format differs from normal fields.
|
||||
/// </summary>
|
||||
public static int ComputeMessageSetExtensionSize(int fieldNumber, IMessage value) {
|
||||
return ComputeTagSize(WireFormat.MessageSetField.Item) * 2 +
|
||||
ComputeUInt32Size(WireFormat.MessageSetField.TypeID, (uint) fieldNumber) +
|
||||
ComputeMessageSize(WireFormat.MessageSetField.Message, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the number of bytes that would be needed to encode an
|
||||
/// unparsed MessageSet extension field to the stream. For
|
||||
/// historical reasons, the wire format differs from normal fields.
|
||||
/// </summary>
|
||||
public static int ComputeRawMessageSetExtensionSize(int fieldNumber, ByteString value) {
|
||||
return ComputeTagSize(WireFormat.MessageSetField.Item) * 2 +
|
||||
ComputeUInt32Size(WireFormat.MessageSetField.TypeID, (uint) fieldNumber) +
|
||||
ComputeBytesSize(WireFormat.MessageSetField.Message, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the number of bytes that would be needed to encode a varint.
|
||||
/// </summary>
|
||||
public static int ComputeRawVarint32Size(uint value) {
|
||||
if ((value & (0xffffffff << 7)) == 0) return 1;
|
||||
if ((value & (0xffffffff << 14)) == 0) return 2;
|
||||
if ((value & (0xffffffff << 21)) == 0) return 3;
|
||||
if ((value & (0xffffffff << 28)) == 0) return 4;
|
||||
return 5;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the number of bytes that would be needed to encode a varint.
|
||||
/// </summary>
|
||||
public static int ComputeRawVarint64Size(ulong value) {
|
||||
if ((value & (0xffffffffffffffffL << 7)) == 0) return 1;
|
||||
if ((value & (0xffffffffffffffffL << 14)) == 0) return 2;
|
||||
if ((value & (0xffffffffffffffffL << 21)) == 0) return 3;
|
||||
if ((value & (0xffffffffffffffffL << 28)) == 0) return 4;
|
||||
if ((value & (0xffffffffffffffffL << 35)) == 0) return 5;
|
||||
if ((value & (0xffffffffffffffffL << 42)) == 0) return 6;
|
||||
if ((value & (0xffffffffffffffffL << 49)) == 0) return 7;
|
||||
if ((value & (0xffffffffffffffffL << 56)) == 0) return 8;
|
||||
if ((value & (0xffffffffffffffffL << 63)) == 0) return 9;
|
||||
return 10;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* field of arbitrary type, including tag, to the stream.
|
||||
*
|
||||
* @param type The field's type.
|
||||
* @param number The field's number.
|
||||
* @param value Object representing the field's value. Must be of the exact
|
||||
* type which would be returned by
|
||||
* {@link Message#getField(Descriptors.FieldDescriptor)} for
|
||||
* this field.
|
||||
*/
|
||||
public static int ComputeFieldSize(Descriptors.FieldDescriptor.Type fieldType, int fieldNumber, Object value) {
|
||||
switch (fieldType) {
|
||||
case Descriptors.FieldDescriptor.Type.Double: return ComputeDoubleSize(fieldNumber, (double)value);
|
||||
case Descriptors.FieldDescriptor.Type.Float: return ComputeFloatSize(fieldNumber, (float)value);
|
||||
case Descriptors.FieldDescriptor.Type.Int64: return ComputeInt64Size(fieldNumber, (long)value);
|
||||
case Descriptors.FieldDescriptor.Type.UInt64: return ComputeUInt64Size(fieldNumber, (ulong)value);
|
||||
case Descriptors.FieldDescriptor.Type.Int32: return ComputeInt32Size(fieldNumber, (int)value);
|
||||
case Descriptors.FieldDescriptor.Type.Fixed64: return ComputeFixed64Size(fieldNumber, (long)value);
|
||||
case Descriptors.FieldDescriptor.Type.Fixed32: return ComputeFixed32Size(fieldNumber, (int)value);
|
||||
case Descriptors.FieldDescriptor.Type.Bool: return ComputeBoolSize(fieldNumber, (bool)value);
|
||||
case Descriptors.FieldDescriptor.Type.String: return ComputeStringSize(fieldNumber, (string)value);
|
||||
case Descriptors.FieldDescriptor.Type.Group: return ComputeGroupSize(fieldNumber, (IMessage)value);
|
||||
case Descriptors.FieldDescriptor.Type.Message: return ComputeMessageSize(fieldNumber, (IMessage)value);
|
||||
case Descriptors.FieldDescriptor.Type.Bytes: return ComputeBytesSize(fieldNumber, (ByteString)value);
|
||||
case Descriptors.FieldDescriptor.Type.UInt32: return ComputeUInt32Size(fieldNumber, (uint)value);
|
||||
case Descriptors.FieldDescriptor.Type.SFixed32: return ComputeSFixed32Size(fieldNumber, (int)value);
|
||||
case Descriptors.FieldDescriptor.Type.SFixed64: return ComputeSFixed64Size(fieldNumber, (long)value);
|
||||
case Descriptors.FieldDescriptor.Type.SInt32: return ComputeSInt32Size(fieldNumber, (int)value);
|
||||
case Descriptors.FieldDescriptor.Type.SInt64: return ComputeSInt64Size(fieldNumber, (long)value);
|
||||
case Descriptors.FieldDescriptor.Type.Enum: return ComputeEnumSize(fieldNumber, ((Descriptors.EnumValueDescriptor)value).Number);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("Invalid field type " + fieldType);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the number of bytes that would be needed to encode a tag.
|
||||
/// </summary>
|
||||
public static int ComputeTagSize(int fieldNumber) {
|
||||
return ComputeRawVarint32Size(WireFormat.MakeTag(fieldNumber, 0));
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Encode a 32-bit value with ZigZag encoding.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// ZigZag encodes signed integers into values that can be efficiently
|
||||
/// encoded with varint. (Otherwise, negative values must be
|
||||
/// sign-extended to 64 bits to be varint encoded, thus always taking
|
||||
/// 10 bytes on the wire.)
|
||||
/// </remarks>
|
||||
public static uint EncodeZigZag32(int n) {
|
||||
// Note: the right-shift must be arithmetic
|
||||
return (uint)((n << 1) ^ (n >> 31));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encode a 64-bit value with ZigZag encoding.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// ZigZag encodes signed integers into values that can be efficiently
|
||||
/// encoded with varint. (Otherwise, negative values must be
|
||||
/// sign-extended to 64 bits to be varint encoded, thus always taking
|
||||
/// 10 bytes on the wire.)
|
||||
/// </remarks>
|
||||
public static ulong EncodeZigZag64(long n) {
|
||||
return (ulong)((n << 1) ^ (n >> 63));
|
||||
}
|
||||
|
||||
private void RefreshBuffer() {
|
||||
if (output == null) {
|
||||
// We're writing to a single buffer.
|
||||
throw new OutOfSpaceException();
|
||||
}
|
||||
|
||||
// Since we have an output stream, this is our buffer
|
||||
// and buffer offset == 0
|
||||
output.Write(buffer, 0, position);
|
||||
position = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that a CodedOutputStream wrapping a flat byte array
|
||||
/// ran out of space.
|
||||
/// </summary>
|
||||
public class OutOfSpaceException : IOException {
|
||||
internal OutOfSpaceException()
|
||||
: base("CodedOutputStream was writing to a flat byte array and ran out of space.") {
|
||||
}
|
||||
}
|
||||
|
||||
public void Flush() {
|
||||
if (output != null) {
|
||||
RefreshBuffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
39
csharp/ProtocolBuffers/Descriptors.cs
Normal file
39
csharp/ProtocolBuffers/Descriptors.cs
Normal file
@ -0,0 +1,39 @@
|
||||
|
||||
using System;
|
||||
|
||||
namespace Google.ProtocolBuffers {
|
||||
public class Descriptors {
|
||||
public class Descriptor {
|
||||
}
|
||||
public class FieldDescriptor {
|
||||
public enum Type {
|
||||
Double,
|
||||
Float,
|
||||
Int64,
|
||||
UInt64,
|
||||
Int32,
|
||||
Fixed64,
|
||||
Fixed32,
|
||||
Bool,
|
||||
String,
|
||||
Group,
|
||||
Message,
|
||||
Bytes,
|
||||
UInt32,
|
||||
SFixed32,
|
||||
SFixed64,
|
||||
SInt32,
|
||||
SInt64,
|
||||
Enum
|
||||
}
|
||||
}
|
||||
|
||||
public class EnumValueDescriptor
|
||||
{
|
||||
public int Number
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
5
csharp/ProtocolBuffers/ExtensionRegistry.cs
Normal file
5
csharp/ProtocolBuffers/ExtensionRegistry.cs
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
namespace Google.ProtocolBuffers {
|
||||
public class ExtensionRegistry {
|
||||
}
|
||||
}
|
227
csharp/ProtocolBuffers/IBuilder.cs
Normal file
227
csharp/ProtocolBuffers/IBuilder.cs
Normal file
@ -0,0 +1,227 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace Google.ProtocolBuffers {
|
||||
|
||||
/// <summary>
|
||||
/// Interface implemented by Protocol Message builders.
|
||||
/// TODO(jonskeet): Consider "SetXXX" methods returning the builder, as well as the properties.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of message</typeparam>
|
||||
public interface IBuilder<T> where T : IMessage<T> {
|
||||
/// <summary>
|
||||
/// Resets all fields to their default values.
|
||||
/// </summary>
|
||||
IBuilder<T> Clear();
|
||||
|
||||
/// <summary>
|
||||
/// Merge the specified other message into the message being
|
||||
/// built. Merging occurs as follows. For each field:
|
||||
/// For singular primitive fields, if the field is set in <paramref name="other"/>,
|
||||
/// then <paramref name="other"/>'s value overwrites the value in this message.
|
||||
/// For singular message fields, if the field is set in <paramref name="other"/>,
|
||||
/// it is merged into the corresponding sub-message of this message using the same
|
||||
/// merging rules.
|
||||
/// For repeated fields, the elements in <paramref name="other"/> are concatenated
|
||||
/// with the elements in this message.
|
||||
/// </summary>
|
||||
/// <param name="other"></param>
|
||||
/// <returns></returns>
|
||||
IBuilder<T> MergeFrom(IMessage<T> other);
|
||||
|
||||
/// <summary>
|
||||
/// Constructs the final message. Once this is called, this Builder instance
|
||||
/// is no longer valid, and calling any other method may throw a
|
||||
/// NullReferenceException. If you need to continue working with the builder
|
||||
/// after calling Build, call Clone first.
|
||||
/// </summary>
|
||||
/// <exception cref="UninitializedMessageException">the message
|
||||
/// is missing one or more required fields; use BuildPartial to bypass
|
||||
/// this check</exception>
|
||||
IMessage<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>
|
||||
IMessage<T> BuildPartial();
|
||||
|
||||
/// <summary>
|
||||
/// Clones this builder.
|
||||
/// TODO(jonskeet): Explain depth of clone.
|
||||
/// </summary>
|
||||
IBuilder<T> Clone();
|
||||
|
||||
/// <summary>
|
||||
/// Returns true iff all required fields in the message and all
|
||||
/// embedded messages are set.
|
||||
/// </summary>
|
||||
bool Initialized { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Parses a message of this type from the input and merges it with this
|
||||
/// message, as if using MergeFrom(IMessage<T>).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Warning: This does not verify that all required fields are present
|
||||
/// in the input message. If you call Build() without setting all
|
||||
/// required fields, it will throw an UninitializedMessageException.
|
||||
/// There are a few good ways to deal with this:
|
||||
/// <list>
|
||||
/// <item>Call Initialized to verify to verify that all required fields are
|
||||
/// set before building.</item>
|
||||
/// <item>Parse the message separately using one of the static ParseFrom
|
||||
/// methods, then use MergeFrom(IMessage<T>) to merge it with
|
||||
/// this one. ParseFrom will throw an InvalidProtocolBufferException
|
||||
/// (an IOException) if some required fields are missing.
|
||||
/// Use BuildPartial to build, which ignores missing required fields.
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
IBuilder<T> MergeFrom(CodedInputStream input);
|
||||
|
||||
/// <summary>
|
||||
/// Like MergeFrom(CodedInputStream), but also parses extensions.
|
||||
/// The extensions that you want to be able to parse must be registered
|
||||
/// in <paramref name="extensionRegistry"/>. Extensions not in the registry
|
||||
/// will be treated as unknown fields.
|
||||
/// </summary>
|
||||
IBuilder<T> MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry);
|
||||
|
||||
/// <summary>
|
||||
/// Get the message's type's descriptor.
|
||||
/// <see cref="IMessage{T}.DescriptorForType"/>
|
||||
/// </summary>
|
||||
Descriptors.Descriptor DescriptorForType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get's the message's type's default instance.
|
||||
/// <see cref="IMessage{T}.DefaultInstanceForType" />
|
||||
/// </summary>
|
||||
IMessage<T> DefaultInstanceForType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Behaves like the equivalent property in IMessage<T>.
|
||||
/// The returned map may or may not reflect future changes to the builder.
|
||||
/// Either way, the returned map is unmodifiable.
|
||||
/// </summary>
|
||||
IDictionary<ProtocolBuffers.Descriptors.FieldDescriptor, object> AllFields { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a builder for messages of the appropriate type for the given field.
|
||||
/// Messages built with this can then be passed to the various mutation properties
|
||||
/// and methods.
|
||||
/// </summary>
|
||||
/// <typeparam name="TField"></typeparam>
|
||||
/// <param name="field"></param>
|
||||
/// <returns></returns>
|
||||
IBuilder<TField> NewBuilderForField<TField>(Descriptors.FieldDescriptor field)
|
||||
where TField : IMessage<TField>;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="IMessage{T}.HasField"/>
|
||||
/// </summary>
|
||||
bool HasField(Descriptors.FieldDescriptor field);
|
||||
|
||||
/// <summary>
|
||||
/// Allows getting and setting of a field.
|
||||
/// <see cref="IMessage{T}.Item(Descriptors.FieldDescriptor)"/>
|
||||
/// </summary>
|
||||
/// <param name="field"></param>
|
||||
/// <returns></returns>
|
||||
object this[Descriptors.FieldDescriptor field] { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Clears the field. This is exactly equivalent to calling the generated
|
||||
/// Clear method corresponding to the field.
|
||||
/// </summary>
|
||||
/// <param name="field"></param>
|
||||
/// <returns></returns>
|
||||
IBuilder<T> ClearField(Descriptors.FieldDescriptor field);
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="IMessage{T}.GetRepeatedFieldCount"/>
|
||||
/// </summary>
|
||||
/// <param name="field"></param>
|
||||
/// <returns></returns>
|
||||
int GetRepeatedFieldCount(Descriptors.FieldDescriptor field);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Allows getting and setting of a repeated field value.
|
||||
/// <see cref="IMessage{T}.Item(Descriptors.FieldDescriptor, int)"/>
|
||||
/// </summary>
|
||||
object this[Descriptors.FieldDescriptor field, int index] { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Appends the given value as a new element for the specified repeated field.
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentException">the field is not a repeated field,
|
||||
/// the field does not belong to this builder's type, or the value is
|
||||
/// of the incorrect type
|
||||
/// </exception>
|
||||
IBuilder<T> AddRepeatedField(Descriptors.FieldDescriptor field, object value);
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="IMessage{T}.UnknownFields"/>
|
||||
/// </summary>
|
||||
UnknownFieldSet UnknownFields { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Merge some unknown fields into the set for this message.
|
||||
/// </summary>
|
||||
IBuilder<T> MergeUnknownFields(UnknownFieldSet unknownFields);
|
||||
|
||||
#region Convenience methods
|
||||
// TODO(jonskeet): Implement these as extension methods?
|
||||
|
||||
/// <summary>
|
||||
/// Parse <paramref name="data"/> as a message of this type and merge
|
||||
/// it with the message being built. This is just a small wrapper around
|
||||
/// MergeFrom(CodedInputStream).
|
||||
/// </summary>
|
||||
IBuilder<T> MergeFrom(ByteString data);
|
||||
|
||||
/// <summary>
|
||||
/// Parse <paramref name="data"/> as a message of this type and merge
|
||||
/// it with the message being built. This is just a small wrapper around
|
||||
/// MergeFrom(CodedInputStream, ExtensionRegistry).
|
||||
/// </summary>
|
||||
IBuilder<T> MergeFrom(ByteString data, ExtensionRegistry extensionRegistry);
|
||||
|
||||
/// <summary>
|
||||
/// Parse <paramref name="data"/> as a message of this type and merge
|
||||
/// it with the message being built. This is just a small wrapper around
|
||||
/// MergeFrom(CodedInputStream).
|
||||
/// </summary>
|
||||
IBuilder<T> MergeFrom(byte[] data);
|
||||
|
||||
/// <summary>
|
||||
/// Parse <paramref name="data"/> as a message of this type and merge
|
||||
/// it with the message being built. This is just a small wrapper around
|
||||
/// MergeFrom(CodedInputStream, ExtensionRegistry).
|
||||
/// </summary>
|
||||
IBuilder<T> MergeFrom(byte[] data, ExtensionRegistry extensionRegistry);
|
||||
|
||||
/// <summary>
|
||||
/// Parse <paramref name="data"/> as a message of this type and merge
|
||||
/// it with the message being built. This is just a small wrapper around
|
||||
/// MergeFrom(CodedInputStream). Note that this method always reads
|
||||
/// the entire input (unless it throws an exception). If you want it to
|
||||
/// stop earlier, you will need to wrap the input in a wrapper
|
||||
/// stream which limits reading. Despite usually reading the entire
|
||||
/// stream, this method never closes the stream.
|
||||
/// </summary>
|
||||
IBuilder<T> MergeFrom(Stream input);
|
||||
|
||||
/// <summary>
|
||||
/// Parse <paramref name="data"/> as a message of this type and merge
|
||||
/// it with the message being built. This is just a small wrapper around
|
||||
/// MergeFrom(CodedInputStream, ExtensionRegistry).
|
||||
/// </summary>
|
||||
IBuilder<T> MergeFrom(Stream input, ExtensionRegistry extensionRegistry);
|
||||
#endregion
|
||||
}
|
||||
}
|
162
csharp/ProtocolBuffers/IMessage.cs
Normal file
162
csharp/ProtocolBuffers/IMessage.cs
Normal file
@ -0,0 +1,162 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Google.ProtocolBuffers {
|
||||
|
||||
/// <summary>
|
||||
/// Non-generic interface.
|
||||
/// TODO(jonskeet): Do we want or need this?
|
||||
/// </summary>
|
||||
public interface IMessage {
|
||||
void WriteTo(CodedOutputStream output);
|
||||
int SerializedSize { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface implemented by all Protocol Buffers messages.
|
||||
/// </summary>
|
||||
public interface IMessage<T> where T : IMessage<T> {
|
||||
/// <summary>
|
||||
/// Returns the message's type's descriptor. This differs from the
|
||||
/// Descriptor property of each generated message class in that this
|
||||
/// method is an abstract method of IMessage whereas Descriptor is
|
||||
/// a static property of a specific class. They return the same thing.
|
||||
/// </summary>
|
||||
Descriptors.Descriptor DescriptorForType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns an instance of this message type with all fields set to
|
||||
/// their default values. This may or may not be a singleton. This differs
|
||||
/// from the DefaultInstance property of each generated message class in that this
|
||||
/// method is an abstract method of IMessage whereas DefaultInstance is
|
||||
/// a static property of a specific class. They return the same thing.
|
||||
/// </summary>
|
||||
IMessage<T> DefaultInstanceForType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a collection of all the fields in this message which are set
|
||||
/// and their corresponding values. A singular ("required" or "optional")
|
||||
/// field is set iff HasField() returns true for that field. A "repeated"
|
||||
/// field is set iff GetRepeatedFieldSize() is greater than zero. The
|
||||
/// values are exactly what would be returned by calling
|
||||
/// GetField(Descriptors.FieldDescriptor) for each field. The map
|
||||
/// is guaranteed to be a sorted map, so iterating over it will return fields
|
||||
/// in order by field number.
|
||||
/// </summary>
|
||||
IDictionary<Descriptors.FieldDescriptor, object> AllFields { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the given field is set. This is exactly equivalent
|
||||
/// to calling the generated "Has" property corresponding to the field.
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentException">the field is a repeated field,
|
||||
/// or it's not a field of this type</exception>
|
||||
bool HasField(Descriptors.FieldDescriptor field);
|
||||
|
||||
/// <summary>
|
||||
/// Obtains the value of the given field, or the default value if
|
||||
/// it isn't set. For value type fields including enums, the boxed
|
||||
/// value is returned. For embedded message fields, the sub-message
|
||||
/// is returned. For repeated fields, an IList<T> is returned.
|
||||
/// </summary>
|
||||
object this[Descriptors.FieldDescriptor field] { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of elements of a repeated field. This is
|
||||
/// exactly equivalent to calling the generated "Count" property
|
||||
/// corresponding to the field.
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentException">the field is not a repeated field,
|
||||
/// or it's not a field of this type</exception>
|
||||
int GetRepeatedFieldCount(Descriptors.FieldDescriptor field);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an element of a repeated field. For value type fields
|
||||
/// including enums, the boxed value is returned. For embedded
|
||||
/// message fields, the sub-message is returned.
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentException">the field is not a repeated field,
|
||||
/// or it's not a field of this type</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">the index is out of
|
||||
/// range for the repeated field's value</exception>
|
||||
object this[Descriptors.FieldDescriptor field, int index] { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the unknown fields for this message.
|
||||
/// </summary>
|
||||
UnknownFieldSet UnknownFields { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns true iff all required fields in the message and all embedded
|
||||
/// messages are set.
|
||||
/// </summary>
|
||||
bool Initialized { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Serializes the message and writes it to the given output stream.
|
||||
/// This does not flush or close the stream.
|
||||
/// </summary>
|
||||
/// <param name="output"></param>
|
||||
void WriteTo(CodedOutputStream output);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of bytes required to encode this message.
|
||||
/// The result is only computed on the first call and memoized after that.
|
||||
/// </summary>
|
||||
int SerializedSize { get; }
|
||||
|
||||
#region Comparison and hashing
|
||||
/// <summary>
|
||||
/// Compares the specified object with this message for equality.
|
||||
/// Returns true iff the given object is a message of the same type
|
||||
/// (as defined by DescriptorForType) and has identical values
|
||||
/// for all its fields.
|
||||
/// </summary>
|
||||
bool Equals(object other);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the hash code value for this message.
|
||||
/// TODO(jonskeet): Specify the hash algorithm, but better than the Java one!
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
int GetHashCode();
|
||||
#endregion
|
||||
|
||||
#region Convenience methods
|
||||
/// <summary>
|
||||
/// Converts the message to a string in protocol buffer text format.
|
||||
/// This is just a trivial wrapper around TextFormat.PrintToString.
|
||||
/// </summary>
|
||||
string ToString();
|
||||
|
||||
/// <summary>
|
||||
/// Serializes the message to a ByteString. This is a trivial wrapper
|
||||
/// around WriteTo(CodedOutputStream).
|
||||
/// </summary>
|
||||
ByteString ToByteString();
|
||||
|
||||
/// <summary>
|
||||
/// Serializes the message to a byte array. This is a trivial wrapper
|
||||
/// around WriteTo(CodedOutputStream).
|
||||
/// </summary>
|
||||
byte[] ToByteArray();
|
||||
|
||||
/// <summary>
|
||||
/// Serializes the message and writes it to the given stream.
|
||||
/// This is just a wrapper around WriteTo(CodedOutputStream). This
|
||||
/// does not flush or close the stream.
|
||||
/// </summary>
|
||||
/// <param name="output"></param>
|
||||
void WriteTo(Stream output);
|
||||
#endregion
|
||||
|
||||
#region Builders
|
||||
/// <summary>
|
||||
/// Constructs a new builder for a message of the same type as this message.
|
||||
/// </summary>
|
||||
IBuilder<T> NewBuilderForType();
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
7
csharp/ProtocolBuffers/InvalidProtocolBufferException.cs
Normal file
7
csharp/ProtocolBuffers/InvalidProtocolBufferException.cs
Normal file
@ -0,0 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Google.ProtocolBuffers {
|
||||
public class InvalidProtocolBufferException : IOException {
|
||||
}
|
||||
}
|
36
csharp/ProtocolBuffers/Properties/AssemblyInfo.cs
Normal file
36
csharp/ProtocolBuffers/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("ProtocolBuffers")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("ProtocolBuffers")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2008")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("279b643d-70e8-47ae-9eb1-500d1c48bab6")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
60
csharp/ProtocolBuffers/ProtocolBuffers.csproj
Normal file
60
csharp/ProtocolBuffers/ProtocolBuffers.csproj
Normal file
@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.21022</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{6908BDCE-D925-43F3-94AC-A531E6DF2591}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Google.ProtocolBuffers</RootNamespace>
|
||||
<AssemblyName>Google.ProtocolBuffers</AssemblyName>
|
||||
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ByteString.cs" />
|
||||
<Compile Include="CodedInputStream.cs" />
|
||||
<Compile Include="CodedOutputStream.cs" />
|
||||
<Compile Include="Descriptors.cs" />
|
||||
<Compile Include="ExtensionRegistry.cs" />
|
||||
<Compile Include="IBuilder.cs" />
|
||||
<Compile Include="IMessage.cs" />
|
||||
<Compile Include="InvalidProtocolBufferException.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="UninitializedMessageException.cs" />
|
||||
<Compile Include="UnknownFieldSet.cs" />
|
||||
<Compile Include="WireFormat.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
6
csharp/ProtocolBuffers/UninitializedMessageException.cs
Normal file
6
csharp/ProtocolBuffers/UninitializedMessageException.cs
Normal file
@ -0,0 +1,6 @@
|
||||
using System;
|
||||
|
||||
namespace Google.ProtocolBuffers {
|
||||
public class UninitializedMessageException : Exception {
|
||||
}
|
||||
}
|
13
csharp/ProtocolBuffers/UnknownFieldSet.cs
Normal file
13
csharp/ProtocolBuffers/UnknownFieldSet.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Google.ProtocolBuffers {
|
||||
public class UnknownFieldSet {
|
||||
public void WriteTo(CodedOutputStream output) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public int SerializedSize { get { return 0; } }
|
||||
}
|
||||
}
|
28
csharp/ProtocolBuffers/WireFormat.cs
Normal file
28
csharp/ProtocolBuffers/WireFormat.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Google.ProtocolBuffers {
|
||||
public class WireFormat {
|
||||
public enum WireType {
|
||||
Varint = 0,
|
||||
Fixed64 = 1,
|
||||
LengthDelimited = 2,
|
||||
StartGroup = 3,
|
||||
EndGroup = 4,
|
||||
Fixed32 = 5
|
||||
}
|
||||
|
||||
internal class MessageSetField {
|
||||
internal const int Item = 1;
|
||||
internal const int TypeID = 2;
|
||||
internal const int Message = 3;
|
||||
}
|
||||
|
||||
public static uint MakeTag(int fieldNumber, WireType type) {
|
||||
|
||||
// FIXME
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user