aboutsummaryrefslogtreecommitdiffhomepage
path: root/csharp/src/ProtocolBuffers.Serialization/AbstractReader.cs
diff options
context:
space:
mode:
Diffstat (limited to 'csharp/src/ProtocolBuffers.Serialization/AbstractReader.cs')
-rw-r--r--csharp/src/ProtocolBuffers.Serialization/AbstractReader.cs686
1 files changed, 686 insertions, 0 deletions
diff --git a/csharp/src/ProtocolBuffers.Serialization/AbstractReader.cs b/csharp/src/ProtocolBuffers.Serialization/AbstractReader.cs
new file mode 100644
index 00000000..99ecec88
--- /dev/null
+++ b/csharp/src/ProtocolBuffers.Serialization/AbstractReader.cs
@@ -0,0 +1,686 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using Google.ProtocolBuffers.Descriptors;
+
+//Disable CS3011: only CLS-compliant members can be abstract
+#pragma warning disable 3011
+
+namespace Google.ProtocolBuffers.Serialization
+{
+ /// <summary>
+ /// Provides a base-class that provides some basic functionality for handling type dispatching
+ /// </summary>
+ public abstract class AbstractReader : ICodedInputStream
+ {
+ private const int DefaultMaxDepth = 64;
+ private int _depth;
+
+ /// <summary> Constructs a new reader </summary>
+ protected AbstractReader() { MaxDepth = DefaultMaxDepth; }
+
+ /// <summary> Gets or sets the maximum recursion depth allowed </summary>
+ public int MaxDepth { get; set; }
+
+ /// <summary>
+ /// Merges the contents of stream into the provided message builder
+ /// </summary>
+ public TBuilder Merge<TBuilder>(TBuilder builder) where TBuilder : IBuilderLite
+ {
+ return Merge(builder, ExtensionRegistry.Empty);
+ }
+
+ /// <summary>
+ /// Merges the contents of stream into the provided message builder
+ /// </summary>
+ public abstract TBuilder Merge<TBuilder>(TBuilder builder, ExtensionRegistry registry)
+ where TBuilder : IBuilderLite;
+
+ /// <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 abstract bool PeekNext(out string field);
+
+ /// <summary>
+ /// Causes the reader to skip past this field
+ /// </summary>
+ protected abstract void Skip();
+
+ /// <summary>
+ /// Returns true if it was able to read a Boolean from the input
+ /// </summary>
+ protected abstract bool Read(ref bool value);
+
+ /// <summary>
+ /// Returns true if it was able to read a Int32 from the input
+ /// </summary>
+ protected abstract bool Read(ref int value);
+
+ /// <summary>
+ /// Returns true if it was able to read a UInt32 from the input
+ /// </summary>
+ protected abstract bool Read(ref uint value);
+
+ /// <summary>
+ /// Returns true if it was able to read a Int64 from the input
+ /// </summary>
+ protected abstract bool Read(ref long value);
+
+ /// <summary>
+ /// Returns true if it was able to read a UInt64 from the input
+ /// </summary>
+ protected abstract bool Read(ref ulong value);
+
+ /// <summary>
+ /// Returns true if it was able to read a Single from the input
+ /// </summary>
+ protected abstract bool Read(ref float value);
+
+ /// <summary>
+ /// Returns true if it was able to read a Double from the input
+ /// </summary>
+ protected abstract bool Read(ref double value);
+
+ /// <summary>
+ /// Returns true if it was able to read a String from the input
+ /// </summary>
+ protected abstract bool Read(ref string value);
+
+ /// <summary>
+ /// Returns true if it was able to read a ByteString from the input
+ /// </summary>
+ protected abstract bool Read(ref ByteString value);
+
+ /// <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 abstract bool ReadEnum(ref object value);
+
+ /// <summary>
+ /// Merges the input stream into the provided IBuilderLite
+ /// </summary>
+ protected abstract bool ReadMessage(IBuilderLite builder, ExtensionRegistry registry);
+
+ /// <summary>
+ /// Reads the root-message preamble specific to this formatter
+ /// </summary>
+ public abstract void ReadMessageStart();
+
+ /// <summary>
+ /// Reads the root-message close specific to this formatter
+ /// </summary>
+ public abstract void ReadMessageEnd();
+
+ /// <summary>
+ /// Merges the input stream into the provided IBuilderLite
+ /// </summary>
+ public virtual bool ReadGroup(IBuilderLite value, ExtensionRegistry registry)
+ {
+ return ReadMessage(value, registry);
+ }
+
+ /// <summary>
+ /// Cursors through the array elements and stops at the end of the array
+ /// </summary>
+ protected virtual IEnumerable<string> ForeachArrayItem(string field)
+ {
+ string next = field;
+ while (true)
+ {
+ yield return next;
+
+ if (!PeekNext(out next) || next != field)
+ {
+ break;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Reads an array of T messages
+ /// </summary>
+ public virtual bool ReadMessageArray<T>(string field, ICollection<T> items, IMessageLite messageType,
+ ExtensionRegistry registry)
+ {
+ bool success = false;
+ foreach (string next in ForeachArrayItem(field))
+ {
+ IBuilderLite builder = messageType.WeakCreateBuilderForType();
+ if (ReadMessage(builder, registry))
+ {
+ items.Add((T) builder.WeakBuild());
+ success |= true;
+ }
+ }
+ return success;
+ }
+
+ /// <summary>
+ /// Reads an array of T messages as a proto-buffer group
+ /// </summary>
+ public virtual bool ReadGroupArray<T>(string field, ICollection<T> items, IMessageLite messageType,
+ ExtensionRegistry registry)
+ {
+ bool success = false;
+ foreach (string next in ForeachArrayItem(field))
+ {
+ IBuilderLite builder = messageType.WeakCreateBuilderForType();
+ if (ReadGroup(builder, registry))
+ {
+ items.Add((T) builder.WeakBuild());
+ success |= true;
+ }
+ }
+ return success;
+ }
+
+ /// <summary>
+ /// Reads an array of System.Enum type T and adds them to the collection
+ /// </summary>
+ public virtual bool ReadEnumArray(string field, ICollection<object> items)
+ {
+ bool success = false;
+ foreach (string next in ForeachArrayItem(field))
+ {
+ object temp = null;
+ if (ReadEnum(ref temp))
+ {
+ items.Add(temp);
+ success |= true;
+ }
+ }
+ return success;
+ }
+
+ /// <summary>
+ /// Reads an array of T, where T is a primitive type defined by FieldType
+ /// </summary>
+ public virtual bool ReadArray<T>(FieldType type, string field, ICollection<T> items)
+ {
+ bool success = false;
+ foreach (string next in ForeachArrayItem(field))
+ {
+ object temp = null;
+ if (ReadField(type, ref temp))
+ {
+ items.Add((T) temp);
+ success |= true;
+ }
+ }
+ return success;
+ }
+
+ /// <summary>
+ /// returns true if it was able to read a single primitive value of FieldType into the value reference
+ /// </summary>
+ public virtual bool ReadField(FieldType type, ref object value)
+ {
+ switch (type)
+ {
+ case FieldType.Bool:
+ {
+ bool temp = false;
+ if (Read(ref temp))
+ {
+ value = temp;
+ }
+ else
+ {
+ return false;
+ }
+ break;
+ }
+ case FieldType.Int64:
+ case FieldType.SInt64:
+ case FieldType.SFixed64:
+ {
+ long temp = 0;
+ if (Read(ref temp))
+ {
+ value = temp;
+ }
+ else
+ {
+ return false;
+ }
+ break;
+ }
+ case FieldType.UInt64:
+ case FieldType.Fixed64:
+ {
+ ulong temp = 0;
+ if (Read(ref temp))
+ {
+ value = temp;
+ }
+ else
+ {
+ return false;
+ }
+ break;
+ }
+ case FieldType.Int32:
+ case FieldType.SInt32:
+ case FieldType.SFixed32:
+ {
+ int temp = 0;
+ if (Read(ref temp))
+ {
+ value = temp;
+ }
+ else
+ {
+ return false;
+ }
+ break;
+ }
+ case FieldType.UInt32:
+ case FieldType.Fixed32:
+ {
+ uint temp = 0;
+ if (Read(ref temp))
+ {
+ value = temp;
+ }
+ else
+ {
+ return false;
+ }
+ break;
+ }
+ case FieldType.Float:
+ {
+ float temp = float.NaN;
+ if (Read(ref temp))
+ {
+ value = temp;
+ }
+ else
+ {
+ return false;
+ }
+ break;
+ }
+ case FieldType.Double:
+ {
+ double temp = float.NaN;
+ if (Read(ref temp))
+ {
+ value = temp;
+ }
+ else
+ {
+ return false;
+ }
+ break;
+ }
+ case FieldType.String:
+ {
+ string temp = null;
+ if (Read(ref temp))
+ {
+ value = temp;
+ }
+ else
+ {
+ return false;
+ }
+ break;
+ }
+ case FieldType.Bytes:
+ {
+ ByteString temp = null;
+ if (Read(ref temp))
+ {
+ value = temp;
+ }
+ else
+ {
+ return false;
+ }
+ break;
+ }
+ default:
+ throw InvalidProtocolBufferException.InvalidTag();
+ }
+ return true;
+ }
+
+ #region ICodedInputStream Members
+
+ bool ICodedInputStream.ReadTag(out uint fieldTag, out string fieldName)
+ {
+ fieldTag = 0;
+ if (PeekNext(out fieldName))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ bool ICodedInputStream.ReadDouble(ref double value)
+ {
+ return Read(ref value);
+ }
+
+ bool ICodedInputStream.ReadFloat(ref float value)
+ {
+ return Read(ref value);
+ }
+
+ bool ICodedInputStream.ReadUInt64(ref ulong value)
+ {
+ return Read(ref value);
+ }
+
+ bool ICodedInputStream.ReadInt64(ref long value)
+ {
+ return Read(ref value);
+ }
+
+ bool ICodedInputStream.ReadInt32(ref int value)
+ {
+ return Read(ref value);
+ }
+
+ bool ICodedInputStream.ReadFixed64(ref ulong value)
+ {
+ return Read(ref value);
+ }
+
+ bool ICodedInputStream.ReadFixed32(ref uint value)
+ {
+ return Read(ref value);
+ }
+
+ bool ICodedInputStream.ReadBool(ref bool value)
+ {
+ return Read(ref value);
+ }
+
+ bool ICodedInputStream.ReadString(ref string value)
+ {
+ return Read(ref value);
+ }
+
+ void ICodedInputStream.ReadGroup(int fieldNumber, IBuilderLite builder, ExtensionRegistry extensionRegistry)
+ {
+ if (_depth++ > MaxDepth)
+ {
+ throw new RecursionLimitExceededException();
+ }
+ ReadGroup(builder, extensionRegistry);
+ _depth--;
+ }
+
+ void ICodedInputStream.ReadUnknownGroup(int fieldNumber, IBuilderLite builder)
+ {
+ throw new NotSupportedException();
+ }
+
+ void ICodedInputStream.ReadMessage(IBuilderLite builder, ExtensionRegistry extensionRegistry)
+ {
+ if (_depth++ > MaxDepth)
+ {
+ throw new RecursionLimitExceededException();
+ }
+ ReadMessage(builder, extensionRegistry);
+ _depth--;
+ }
+
+ bool ICodedInputStream.ReadBytes(ref ByteString value)
+ {
+ return Read(ref value);
+ }
+
+ bool ICodedInputStream.ReadUInt32(ref uint value)
+ {
+ return Read(ref value);
+ }
+
+ bool ICodedInputStream.ReadEnum(ref IEnumLite value, out object unknown, IEnumLiteMap mapping)
+ {
+ value = null;
+ unknown = null;
+ if (ReadEnum(ref unknown))
+ {
+ if (unknown is int)
+ {
+ value = mapping.FindValueByNumber((int) unknown);
+ }
+ else if (unknown is string)
+ {
+ value = mapping.FindValueByName((string) unknown);
+ }
+ return value != null;
+ }
+ return false;
+ }
+
+ bool ICodedInputStream.ReadEnum<T>(ref T value, out object rawValue)
+ {
+ rawValue = null;
+ if (ReadEnum(ref rawValue))
+ {
+ if (!EnumParser<T>.TryConvert(rawValue, ref value))
+ {
+ value = default(T);
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ bool ICodedInputStream.ReadSFixed32(ref int value)
+ {
+ return Read(ref value);
+ }
+
+ bool ICodedInputStream.ReadSFixed64(ref long value)
+ {
+ return Read(ref value);
+ }
+
+ bool ICodedInputStream.ReadSInt32(ref int value)
+ {
+ return Read(ref value);
+ }
+
+ bool ICodedInputStream.ReadSInt64(ref long value)
+ {
+ return Read(ref value);
+ }
+
+ void ICodedInputStream.ReadPrimitiveArray(FieldType fieldType, uint fieldTag, string fieldName,
+ ICollection<object> list)
+ {
+ ReadArray(fieldType, fieldName, list);
+ }
+
+ void ICodedInputStream.ReadEnumArray(uint fieldTag, string fieldName, ICollection<IEnumLite> list,
+ out ICollection<object> unknown, IEnumLiteMap mapping)
+ {
+ unknown = null;
+ List<object> array = new List<object>();
+ if (ReadEnumArray(fieldName, array))
+ {
+ foreach (object rawValue in array)
+ {
+ IEnumLite item = null;
+ if (rawValue is int)
+ {
+ item = mapping.FindValueByNumber((int) rawValue);
+ }
+ else if (rawValue is string)
+ {
+ item = mapping.FindValueByName((string) rawValue);
+ }
+
+ if (item != null)
+ {
+ list.Add(item);
+ }
+ else
+ {
+ if (unknown == null)
+ {
+ unknown = new List<object>();
+ }
+ unknown.Add(rawValue);
+ }
+ }
+ }
+ }
+
+ void ICodedInputStream.ReadEnumArray<T>(uint fieldTag, string fieldName, ICollection<T> list,
+ out ICollection<object> unknown)
+ {
+ unknown = null;
+ List<object> array = new List<object>();
+ if (ReadEnumArray(fieldName, array))
+ {
+ foreach (object rawValue in array)
+ {
+ T val = default(T);
+ if (EnumParser<T>.TryConvert(rawValue, ref val))
+ {
+ list.Add(val);
+ }
+ else
+ {
+ if (unknown == null)
+ {
+ unknown = new List<object>();
+ }
+ unknown.Add(rawValue);
+ }
+ }
+ }
+ }
+
+ void ICodedInputStream.ReadMessageArray<T>(uint fieldTag, string fieldName, ICollection<T> list, T messageType,
+ ExtensionRegistry registry)
+ {
+ if (_depth++ > MaxDepth)
+ {
+ throw new RecursionLimitExceededException();
+ }
+ ReadMessageArray(fieldName, list, messageType, registry);
+ _depth--;
+ }
+
+ void ICodedInputStream.ReadGroupArray<T>(uint fieldTag, string fieldName, ICollection<T> list, T messageType,
+ ExtensionRegistry registry)
+ {
+ if (_depth++ > MaxDepth)
+ {
+ throw new RecursionLimitExceededException();
+ }
+ ReadGroupArray(fieldName, list, messageType, registry);
+ _depth--;
+ }
+
+ bool ICodedInputStream.ReadPrimitiveField(FieldType fieldType, ref object value)
+ {
+ return ReadField(fieldType, ref value);
+ }
+
+ bool ICodedInputStream.IsAtEnd
+ {
+ get
+ {
+ string next;
+ return PeekNext(out next) == false;
+ }
+ }
+
+ bool ICodedInputStream.SkipField()
+ {
+ Skip();
+ return true;
+ }
+
+ void ICodedInputStream.ReadStringArray(uint fieldTag, string fieldName, ICollection<string> list)
+ {
+ ReadArray(FieldType.String, fieldName, list);
+ }
+
+ void ICodedInputStream.ReadBytesArray(uint fieldTag, string fieldName, ICollection<ByteString> list)
+ {
+ ReadArray(FieldType.Bytes, fieldName, list);
+ }
+
+ void ICodedInputStream.ReadBoolArray(uint fieldTag, string fieldName, ICollection<bool> list)
+ {
+ ReadArray(FieldType.Bool, fieldName, list);
+ }
+
+ void ICodedInputStream.ReadInt32Array(uint fieldTag, string fieldName, ICollection<int> list)
+ {
+ ReadArray(FieldType.Int32, fieldName, list);
+ }
+
+ void ICodedInputStream.ReadSInt32Array(uint fieldTag, string fieldName, ICollection<int> list)
+ {
+ ReadArray(FieldType.SInt32, fieldName, list);
+ }
+
+ void ICodedInputStream.ReadUInt32Array(uint fieldTag, string fieldName, ICollection<uint> list)
+ {
+ ReadArray(FieldType.UInt32, fieldName, list);
+ }
+
+ void ICodedInputStream.ReadFixed32Array(uint fieldTag, string fieldName, ICollection<uint> list)
+ {
+ ReadArray(FieldType.Fixed32, fieldName, list);
+ }
+
+ void ICodedInputStream.ReadSFixed32Array(uint fieldTag, string fieldName, ICollection<int> list)
+ {
+ ReadArray(FieldType.SFixed32, fieldName, list);
+ }
+
+ void ICodedInputStream.ReadInt64Array(uint fieldTag, string fieldName, ICollection<long> list)
+ {
+ ReadArray(FieldType.Int64, fieldName, list);
+ }
+
+ void ICodedInputStream.ReadSInt64Array(uint fieldTag, string fieldName, ICollection<long> list)
+ {
+ ReadArray(FieldType.SInt64, fieldName, list);
+ }
+
+ void ICodedInputStream.ReadUInt64Array(uint fieldTag, string fieldName, ICollection<ulong> list)
+ {
+ ReadArray(FieldType.UInt64, fieldName, list);
+ }
+
+ void ICodedInputStream.ReadFixed64Array(uint fieldTag, string fieldName, ICollection<ulong> list)
+ {
+ ReadArray(FieldType.Fixed64, fieldName, list);
+ }
+
+ void ICodedInputStream.ReadSFixed64Array(uint fieldTag, string fieldName, ICollection<long> list)
+ {
+ ReadArray(FieldType.SFixed64, fieldName, list);
+ }
+
+ void ICodedInputStream.ReadDoubleArray(uint fieldTag, string fieldName, ICollection<double> list)
+ {
+ ReadArray(FieldType.Double, fieldName, list);
+ }
+
+ void ICodedInputStream.ReadFloatArray(uint fieldTag, string fieldName, ICollection<float> list)
+ {
+ ReadArray(FieldType.Float, fieldName, list);
+ }
+
+ #endregion
+ }
+} \ No newline at end of file