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