aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorcsharptest <roger@csharptest.net>2011-06-10 18:01:34 -0500
committerrogerk <devnull@localhost>2011-06-10 18:01:34 -0500
commit4dc0dfb1546998b15a5e98d5dde6154d463365f2 (patch)
tree2dc8961df1e5c67e215c5e119a2989ba04a58511 /src
parentddb74eb6a45e758f6690f237fdf60b98d76e02fb (diff)
downloadprotobuf-4dc0dfb1546998b15a5e98d5dde6154d463365f2.tar.gz
protobuf-4dc0dfb1546998b15a5e98d5dde6154d463365f2.tar.bz2
protobuf-4dc0dfb1546998b15a5e98d5dde6154d463365f2.zip
Added initial DictionaryReader/Writer implementations
Diffstat (limited to 'src')
-rw-r--r--src/ProtoBench/Program.cs6
-rw-r--r--src/ProtocolBuffers.Test/CompatTests/CompatibilityTests.cs13
-rw-r--r--src/ProtocolBuffers.Test/CompatTests/DictionaryCompatibilityTests.cs37
-rw-r--r--src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj1
-rw-r--r--src/ProtocolBuffers/ProtocolBuffers.csproj2
-rw-r--r--src/ProtocolBuffers/Serialization/AbstractWriter.cs7
-rw-r--r--src/ProtocolBuffers/Serialization/DictionaryReader.cs227
-rw-r--r--src/ProtocolBuffers/Serialization/DictionaryWriter.cs172
-rw-r--r--src/ProtocolBuffers/Serialization/JsonFormatWriter.cs10
-rw-r--r--src/ProtocolBuffers/Serialization/XmlFormatWriter.cs2
10 files changed, 455 insertions, 22 deletions
diff --git a/src/ProtoBench/Program.cs b/src/ProtoBench/Program.cs
index 2239fe08..34860f33 100644
--- a/src/ProtoBench/Program.cs
+++ b/src/ProtoBench/Program.cs
@@ -137,6 +137,10 @@ namespace Google.ProtocolBuffers.ProtoBench
new JsonFormatWriter(temp).WriteMessage(sampleMessage);
string jsonMessageText = temp.ToString();
+ IDictionary<string, object> dictionary = new Dictionary<string, object>(StringComparer.Ordinal);
+ new DictionaryWriter(dictionary).WriteMessage(sampleMessage);
+
+
//Serializers
if(!FastTest) RunBenchmark("Serialize to byte string", inputData.Length, () => sampleMessage.ToByteString());
RunBenchmark("Serialize to byte array", inputData.Length, () => sampleMessage.ToByteArray());
@@ -145,6 +149,7 @@ namespace Google.ProtocolBuffers.ProtoBench
RunBenchmark("Serialize to xml", xmlMessageText.Length, () => new XmlFormatWriter(new StringWriter()).WriteMessage(sampleMessage));
RunBenchmark("Serialize to json", jsonMessageText.Length, () => new JsonFormatWriter(new StringWriter()).WriteMessage(sampleMessage));
+ RunBenchmark("Serialize to dictionary", sampleMessage.SerializedSize, () => new DictionaryWriter().WriteMessage(sampleMessage));
//Deserializers
if (!FastTest) RunBenchmark("Deserialize from byte string", inputData.Length,
@@ -168,6 +173,7 @@ namespace Google.ProtocolBuffers.ProtoBench
RunBenchmark("Deserialize from xml", xmlMessageText.Length, () => new XmlFormatReader(xmlMessageText).Merge(defaultMessage.WeakCreateBuilderForType()).WeakBuild());
RunBenchmark("Deserialize from json", jsonMessageText.Length, () => new JsonFormatReader(jsonMessageText).Merge(defaultMessage.WeakCreateBuilderForType()).WeakBuild());
+ RunBenchmark("Deserialize from dictionary", sampleMessage.SerializedSize, () => new DictionaryReader(dictionary).Merge(defaultMessage.WeakCreateBuilderForType()).WeakBuild());
Console.WriteLine();
return true;
diff --git a/src/ProtocolBuffers.Test/CompatTests/CompatibilityTests.cs b/src/ProtocolBuffers.Test/CompatTests/CompatibilityTests.cs
index 49c56290..0306c41e 100644
--- a/src/ProtocolBuffers.Test/CompatTests/CompatibilityTests.cs
+++ b/src/ProtocolBuffers.Test/CompatTests/CompatibilityTests.cs
@@ -14,6 +14,11 @@ namespace Google.ProtocolBuffers.CompatTests
where TMessage : IMessageLite<TMessage, TBuilder>
where TBuilder : IBuilderLite<TMessage, TBuilder>;
+ protected virtual void AssertOutputEquals(object lhs, object rhs)
+ {
+ Assert.AreEqual(lhs, rhs);
+ }
+
[Test]
public virtual void RoundTripMessage1OptimizeSize()
{
@@ -23,7 +28,7 @@ namespace Google.ProtocolBuffers.CompatTests
SizeMessage1 copy = DeerializeMessage<SizeMessage1, SizeMessage1.Builder>(content, SizeMessage1.CreateBuilder(), ExtensionRegistry.Empty).Build();
Assert.AreEqual(msg, copy);
- Assert.AreEqual(content, SerializeMessage<SizeMessage1,SizeMessage1.Builder>(copy));
+ AssertOutputEquals(content, SerializeMessage<SizeMessage1, SizeMessage1.Builder>(copy));
Assert.AreEqual(TestResources.google_message1, copy.ToByteArray());
}
@@ -36,7 +41,7 @@ namespace Google.ProtocolBuffers.CompatTests
SizeMessage2 copy = DeerializeMessage<SizeMessage2, SizeMessage2.Builder>(content, SizeMessage2.CreateBuilder(), ExtensionRegistry.Empty).Build();
Assert.AreEqual(msg, copy);
- Assert.AreEqual(content, SerializeMessage<SizeMessage2, SizeMessage2.Builder>(copy));
+ AssertOutputEquals(content, SerializeMessage<SizeMessage2, SizeMessage2.Builder>(copy));
Assert.AreEqual(TestResources.google_message2, copy.ToByteArray());
}
@@ -49,7 +54,7 @@ namespace Google.ProtocolBuffers.CompatTests
SpeedMessage1 copy = DeerializeMessage<SpeedMessage1, SpeedMessage1.Builder>(content, SpeedMessage1.CreateBuilder(), ExtensionRegistry.Empty).Build();
Assert.AreEqual(msg, copy);
- Assert.AreEqual(content, SerializeMessage<SpeedMessage1, SpeedMessage1.Builder>(copy));
+ AssertOutputEquals(content, SerializeMessage<SpeedMessage1, SpeedMessage1.Builder>(copy));
Assert.AreEqual(TestResources.google_message1, copy.ToByteArray());
}
@@ -62,7 +67,7 @@ namespace Google.ProtocolBuffers.CompatTests
SpeedMessage2 copy = DeerializeMessage<SpeedMessage2, SpeedMessage2.Builder>(content, SpeedMessage2.CreateBuilder(), ExtensionRegistry.Empty).Build();
Assert.AreEqual(msg, copy);
- Assert.AreEqual(content, SerializeMessage<SpeedMessage2, SpeedMessage2.Builder>(copy));
+ AssertOutputEquals(content, SerializeMessage<SpeedMessage2, SpeedMessage2.Builder>(copy));
Assert.AreEqual(TestResources.google_message2, copy.ToByteArray());
}
diff --git a/src/ProtocolBuffers.Test/CompatTests/DictionaryCompatibilityTests.cs b/src/ProtocolBuffers.Test/CompatTests/DictionaryCompatibilityTests.cs
new file mode 100644
index 00000000..8de82ea9
--- /dev/null
+++ b/src/ProtocolBuffers.Test/CompatTests/DictionaryCompatibilityTests.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using Google.ProtocolBuffers.Serialization;
+using NUnit.Framework;
+
+namespace Google.ProtocolBuffers.CompatTests
+{
+ [TestFixture]
+ public class DictionaryCompatibilityTests : CompatibilityTests
+ {
+ protected override object SerializeMessage<TMessage, TBuilder>(TMessage message)
+ {
+ DictionaryWriter writer = new DictionaryWriter();
+ writer.WriteMessage(message);
+ return writer.ToDictionary();
+ }
+
+ protected override TBuilder DeerializeMessage<TMessage, TBuilder>(object message, TBuilder builder, ExtensionRegistry registry)
+ {
+ new DictionaryReader((IDictionary<string, object>)message).Merge(builder);
+ return builder;
+ }
+
+ protected override void AssertOutputEquals(object lhs, object rhs)
+ {
+ IDictionary<string, object> left = (IDictionary<string, object>)lhs;
+ IDictionary<string, object> right = (IDictionary<string, object>)rhs;
+
+ Assert.AreEqual(
+ String.Join(",", new List<string>(left.Keys).ToArray()),
+ String.Join(",", new List<string>(right.Keys).ToArray())
+ );
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj b/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
index 199e410a..04a02999 100644
--- a/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
+++ b/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
@@ -77,6 +77,7 @@
<Compile Include="Collections\PopsicleListTest.cs" />
<Compile Include="CompatTests\BinaryCompatibilityTests.cs" />
<Compile Include="CompatTests\CompatibilityTests.cs" />
+ <Compile Include="CompatTests\DictionaryCompatibilityTests.cs" />
<Compile Include="CompatTests\JsonCompatibilityTests.cs" />
<Compile Include="CompatTests\TestResources.Designer.cs">
<AutoGen>True</AutoGen>
diff --git a/src/ProtocolBuffers/ProtocolBuffers.csproj b/src/ProtocolBuffers/ProtocolBuffers.csproj
index 19a97a46..22f3c139 100644
--- a/src/ProtocolBuffers/ProtocolBuffers.csproj
+++ b/src/ProtocolBuffers/ProtocolBuffers.csproj
@@ -184,6 +184,8 @@
<Compile Include="Serialization\AbstractTextReader.cs" />
<Compile Include="Serialization\AbstractTextWriter.cs" />
<Compile Include="Serialization\AbstractWriter.cs" />
+ <Compile Include="Serialization\DictionaryReader.cs" />
+ <Compile Include="Serialization\DictionaryWriter.cs" />
<Compile Include="Serialization\JsonFormatReader.cs" />
<Compile Include="Serialization\JsonFormatWriter.cs" />
<Compile Include="Serialization\JsonTextCursor.cs" />
diff --git a/src/ProtocolBuffers/Serialization/AbstractWriter.cs b/src/ProtocolBuffers/Serialization/AbstractWriter.cs
index d8a0c0a1..96153162 100644
--- a/src/ProtocolBuffers/Serialization/AbstractWriter.cs
+++ b/src/ProtocolBuffers/Serialization/AbstractWriter.cs
@@ -42,13 +42,6 @@ namespace Google.ProtocolBuffers.Serialization
public abstract void WriteMessage(IMessageLite message);
/// <summary>
- /// Writes a message
- /// </summary>
- public abstract void WriteMessage(string field, IMessageLite message);
-
-
-
- /// <summary>
/// Writes a Boolean value
/// </summary>
protected abstract void Write(string field, Boolean value);
diff --git a/src/ProtocolBuffers/Serialization/DictionaryReader.cs b/src/ProtocolBuffers/Serialization/DictionaryReader.cs
new file mode 100644
index 00000000..f8ef1eda
--- /dev/null
+++ b/src/ProtocolBuffers/Serialization/DictionaryReader.cs
@@ -0,0 +1,227 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers.Serialization
+{
+ /// <summary>
+ /// Allows reading messages from a name/value dictionary
+ /// </summary>
+ public class DictionaryReader : AbstractReader
+ {
+ private readonly IEnumerator<KeyValuePair<string, object>> _input;
+ private bool _ready;
+
+ /// <summary>
+ /// Creates a dictionary reader from an enumeration of KeyValuePair data, like an IDictionary
+ /// </summary>
+ public DictionaryReader(IEnumerable<KeyValuePair<string, object>> input)
+ {
+ _input = input.GetEnumerator();
+ _ready = _input.MoveNext();
+ }
+
+ /// <summary>
+ /// Merges the contents of stream into the provided message builder
+ /// </summary>
+ public override TBuilder Merge<TBuilder>(TBuilder builder, ExtensionRegistry registry)
+ {
+ builder.WeakMergeFrom(this, registry);
+ return builder;
+ }
+
+ /// <summary>
+ /// Peeks at the next field in the input stream and returns what information is available.
+ /// </summary>
+ /// <remarks>
+ /// This may be called multiple times without actually reading the field. Only after the field
+ /// is either read, or skipped, should PeekNext return a different value.
+ /// </remarks>
+ protected override bool PeekNext(out string field)
+ {
+ field = _ready ? _input.Current.Key : null;
+ return _ready;
+ }
+
+ /// <summary>
+ /// Causes the reader to skip past this field
+ /// </summary>
+ protected override void Skip()
+ {
+ _ready = _input.MoveNext();
+ }
+
+ private bool GetValue<T>(ref T value)
+ {
+ if (!_ready) return false;
+
+ object obj = _input.Current.Value;
+ if (obj is T)
+ value = (T)obj;
+ else
+ {
+ try
+ {
+ if (obj is IConvertible)
+ value = (T)Convert.ChangeType(obj, typeof(T));
+ else
+ value = (T)obj;
+ }
+ catch
+ {
+ _ready = _input.MoveNext();
+ return false;
+ }
+ }
+ _ready = _input.MoveNext();
+ return true;
+ }
+
+ /// <summary>
+ /// Returns true if it was able to read a Boolean from the input
+ /// </summary>
+ protected override bool Read(ref bool value)
+ {
+ return GetValue(ref value);
+ }
+
+ /// <summary>
+ /// Returns true if it was able to read a Int32 from the input
+ /// </summary>
+ protected override bool Read(ref int value)
+ {
+ return GetValue(ref value);
+ }
+
+ /// <summary>
+ /// Returns true if it was able to read a UInt32 from the input
+ /// </summary>
+ [CLSCompliant(false)]
+ protected override bool Read(ref uint value)
+ {
+ return GetValue(ref value);
+ }
+
+ /// <summary>
+ /// Returns true if it was able to read a Int64 from the input
+ /// </summary>
+ protected override bool Read(ref long value)
+ {
+ return GetValue(ref value);
+ }
+
+ /// <summary>
+ /// Returns true if it was able to read a UInt64 from the input
+ /// </summary>
+ [CLSCompliant(false)]
+ protected override bool Read(ref ulong value)
+ {
+ return GetValue(ref value);
+ }
+
+ /// <summary>
+ /// Returns true if it was able to read a Single from the input
+ /// </summary>
+ protected override bool Read(ref float value)
+ {
+ return GetValue(ref value);
+ }
+
+ /// <summary>
+ /// Returns true if it was able to read a Double from the input
+ /// </summary>
+ protected override bool Read(ref double value)
+ {
+ return GetValue(ref value);
+ }
+
+ /// <summary>
+ /// Returns true if it was able to read a String from the input
+ /// </summary>
+ protected override bool Read(ref string value)
+ {
+ return GetValue(ref value);
+ }
+
+ /// <summary>
+ /// Returns true if it was able to read a ByteString from the input
+ /// </summary>
+ protected override bool Read(ref ByteString value)
+ {
+ byte[] rawbytes = null;
+ if (GetValue(ref rawbytes))
+ {
+ value = ByteString.AttachBytes(rawbytes);
+ return true;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// returns true if it was able to read a single value into the value reference. The value
+ /// stored may be of type System.String, System.Int32, or an IEnumLite from the IEnumLiteMap.
+ /// </summary>
+ protected override bool ReadEnum(ref object value)
+ {
+ return GetValue(ref value);
+ }
+
+ /// <summary>
+ /// Merges the input stream into the provided IBuilderLite
+ /// </summary>
+ protected override bool ReadMessage(IBuilderLite builder, ExtensionRegistry registry)
+ {
+ IDictionary<string, object> values = null;
+ if (GetValue(ref values))
+ {
+ new DictionaryReader(values).Merge(builder, registry);
+ return true;
+ }
+ return false;
+ }
+
+ public override bool ReadArray<T>(FieldType type, string field, ICollection<T> items)
+ {
+ object[] array = null;
+ if (GetValue(ref array))
+ {
+ foreach (T item in array)
+ items.Add(item);
+ return true;
+ }
+ return false;
+ }
+
+ public override bool ReadEnumArray(string field, ICollection<object> items)
+ {
+ object[] array = null;
+ if (GetValue(ref array))
+ {
+ foreach (object item in array)
+ items.Add(item);
+ return true;
+ }
+ return false;
+ }
+
+ public override bool ReadMessageArray<T>(string field, ICollection<T> items, IMessageLite messageType, ExtensionRegistry registry)
+ {
+ object[] array = null;
+ if (GetValue(ref array))
+ {
+ foreach (IDictionary<string, object> item in array)
+ {
+ IBuilderLite builder = messageType.WeakCreateBuilderForType();
+ new DictionaryReader(item).Merge(builder);
+ items.Add((T)builder.WeakBuild());
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public override bool ReadGroupArray<T>(string field, ICollection<T> items, IMessageLite messageType, ExtensionRegistry registry)
+ { return ReadMessageArray(field, items, messageType, registry); }
+ }
+}
diff --git a/src/ProtocolBuffers/Serialization/DictionaryWriter.cs b/src/ProtocolBuffers/Serialization/DictionaryWriter.cs
new file mode 100644
index 00000000..596a9262
--- /dev/null
+++ b/src/ProtocolBuffers/Serialization/DictionaryWriter.cs
@@ -0,0 +1,172 @@
+using System;
+using System.Collections.Generic;
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers.Serialization
+{
+ /// <summary>
+ /// Allows writing messages to a name/value dictionary
+ /// </summary>
+ public class DictionaryWriter : AbstractWriter
+ {
+ private readonly IDictionary<string, object> _output;
+
+ /// <summary>
+ /// Constructs a writer using a new dictionary
+ /// </summary>
+ public DictionaryWriter()
+ : this(new Dictionary<string,object>())
+ { }
+
+ /// <summary>
+ /// Constructs a writer using an existing dictionary
+ /// </summary>
+ public DictionaryWriter(IDictionary<string, object> output)
+ {
+ ThrowHelper.ThrowIfNull(output, "output");
+ _output = output;
+ }
+
+ /// <summary>
+ /// Accesses the dictionary that is backing this writer
+ /// </summary>
+ public IDictionary<string, object> ToDictionary() { return _output; }
+
+ /// <summary>
+ /// Writes the message to the the formatted stream.
+ /// </summary>
+ public override void WriteMessage(IMessageLite message)
+ {
+ message.WriteTo(this);
+ }
+
+ /// <summary>
+ /// Writes a Boolean value
+ /// </summary>
+ protected override void Write(string field, bool value)
+ {
+ _output[field] = value;
+ }
+
+ /// <summary>
+ /// Writes a Int32 value
+ /// </summary>
+ protected override void Write(string field, int value)
+ {
+ _output[field] = value;
+ }
+
+ /// <summary>
+ /// Writes a UInt32 value
+ /// </summary>
+ [CLSCompliant(false)]
+ protected override void Write(string field, uint value)
+ {
+ _output[field] = value;
+ }
+
+ /// <summary>
+ /// Writes a Int64 value
+ /// </summary>
+ protected override void Write(string field, long value)
+ {
+ _output[field] = value;
+ }
+
+ /// <summary>
+ /// Writes a UInt64 value
+ /// </summary>
+ [CLSCompliant(false)]
+ protected override void Write(string field, ulong value)
+ {
+ _output[field] = value;
+ }
+
+ /// <summary>
+ /// Writes a Single value
+ /// </summary>
+ protected override void Write(string field, float value)
+ {
+ _output[field] = value;
+ }
+
+ /// <summary>
+ /// Writes a Double value
+ /// </summary>
+ protected override void Write(string field, double value)
+ {
+ _output[field] = value;
+ }
+
+ /// <summary>
+ /// Writes a String value
+ /// </summary>
+ protected override void Write(string field, string value)
+ {
+ _output[field] = value;
+ }
+
+ /// <summary>
+ /// Writes a set of bytes
+ /// </summary>
+ protected override void Write(string field, ByteString value)
+ {
+ _output[field] = value.ToByteArray();
+ }
+
+ /// <summary>
+ /// Writes a message or group as a field
+ /// </summary>
+ protected override void WriteMessageOrGroup(string field, IMessageLite message)
+ {
+ DictionaryWriter writer = new DictionaryWriter();
+ writer.WriteMessage(message);
+
+ _output[field] = writer.ToDictionary();
+ }
+
+ /// <summary>
+ /// Writes a System.Enum by the numeric and textual value
+ /// </summary>
+ protected override void WriteEnum(string field, int number, string name)
+ {
+ _output[field] = number;
+ }
+
+ /// <summary>
+ /// Writes an array of field values
+ /// </summary>
+ protected override void WriteArray(FieldType fieldType, string field, System.Collections.IEnumerable items)
+ {
+ List<object> objects = new List<object>();
+ foreach (object o in items)
+ {
+ switch (fieldType)
+ {
+ case FieldType.Group:
+ case FieldType.Message:
+ {
+ DictionaryWriter writer = new DictionaryWriter();
+ writer.WriteMessage((IMessageLite)o);
+ objects.Add(writer.ToDictionary());
+ }
+ break;
+ case FieldType.Bytes:
+ objects.Add(((ByteString)o).ToByteArray());
+ break;
+ case FieldType.Enum:
+ if (o is IEnumLite)
+ objects.Add(((IEnumLite)o).Number);
+ else
+ objects.Add((int)o);
+ break;
+ default:
+ objects.Add(o);
+ break;
+ }
+ }
+
+ _output[field] = objects.ToArray();
+ }
+ }
+}
diff --git a/src/ProtocolBuffers/Serialization/JsonFormatWriter.cs b/src/ProtocolBuffers/Serialization/JsonFormatWriter.cs
index 5d5144ba..0baf6cac 100644
--- a/src/ProtocolBuffers/Serialization/JsonFormatWriter.cs
+++ b/src/ProtocolBuffers/Serialization/JsonFormatWriter.cs
@@ -264,16 +264,6 @@ namespace Google.ProtocolBuffers.Serialization
}
/// <summary>
- /// Writes a message
- /// </summary>
- [System.ComponentModel.Browsable(false)]
- [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
- public override void WriteMessage(string field, IMessageLite message)
- {
- WriteMessage(message);
- }
-
- /// <summary>
/// Used in streaming arrays of objects to the writer
/// </summary>
/// <example>
diff --git a/src/ProtocolBuffers/Serialization/XmlFormatWriter.cs b/src/ProtocolBuffers/Serialization/XmlFormatWriter.cs
index 5ed96651..b5dbf5fa 100644
--- a/src/ProtocolBuffers/Serialization/XmlFormatWriter.cs
+++ b/src/ProtocolBuffers/Serialization/XmlFormatWriter.cs
@@ -73,7 +73,7 @@ namespace Google.ProtocolBuffers.Serialization
/// <summary>
/// Writes a message as an element with the given name
/// </summary>
- public override void WriteMessage(string elementName, IMessageLite message)
+ public void WriteMessage(string elementName, IMessageLite message)
{
if (TestOption(XmlWriterOptions.OutputJsonTypes))
{