|
@@ -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); }
|
|
|
+ }
|
|
|
+}
|