aboutsummaryrefslogtreecommitdiffhomepage
path: root/csharp/src/ProtocolBuffers.Serialization/DictionaryReader.cs
diff options
context:
space:
mode:
Diffstat (limited to 'csharp/src/ProtocolBuffers.Serialization/DictionaryReader.cs')
-rw-r--r--csharp/src/ProtocolBuffers.Serialization/DictionaryReader.cs265
1 files changed, 265 insertions, 0 deletions
diff --git a/csharp/src/ProtocolBuffers.Serialization/DictionaryReader.cs b/csharp/src/ProtocolBuffers.Serialization/DictionaryReader.cs
new file mode 100644
index 00000000..971d0fee
--- /dev/null
+++ b/csharp/src/ProtocolBuffers.Serialization/DictionaryReader.cs
@@ -0,0 +1,265 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+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>
+ /// No-op
+ /// </summary>
+ public override void ReadMessageStart()
+ { }
+
+ /// <summary>
+ /// No-op
+ /// </summary>
+ public override void ReadMessageEnd()
+ { }
+
+ /// <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), FrameworkPortability.InvariantCulture);
+ }
+ 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>
+ 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>
+ 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.CopyFrom(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))
+ {
+ if (typeof(T) == typeof(ByteString))
+ {
+ ICollection<ByteString> output = (ICollection<ByteString>) items;
+ foreach (byte[] item in array)
+ {
+ output.Add(ByteString.CopyFrom(item));
+ }
+ }
+ else
+ {
+ 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);
+ }
+ }
+} \ No newline at end of file