public ReaderContext(Stream stream) { this.Reader = new ProtoReader(stream, TypeModel.Create(), null); this.ReadingAction = ReadingActionType.ReadHeader; this.Root = new VisitingNode(NoParent); this.ParentVisitingNode = this.Root; }
static public int Dispose(IntPtr l) { try { ProtoBuf.ProtoReader self = (ProtoBuf.ProtoReader)checkSelf(l); self.Dispose(); pushValue(l, true); return(1); } catch (Exception e) { return(error(l, e)); } }
static public int get_WireType(IntPtr l) { try { ProtoBuf.ProtoReader self = (ProtoBuf.ProtoReader)checkSelf(l); pushValue(l, true); pushEnum(l, (int)self.WireType); return(2); } catch (Exception e) { return(error(l, e)); } }
static public int get_Model(IntPtr l) { try { ProtoBuf.ProtoReader self = (ProtoBuf.ProtoReader)checkSelf(l); pushValue(l, true); pushValue(l, self.Model); return(2); } catch (Exception e) { return(error(l, e)); } }
/// <summary> /// The deserialize. /// </summary> /// <param name="num"> /// The num. /// </param> /// <param name="obj"> /// The obj. /// </param> /// <param name="protoReader"> /// The proto reader. /// </param> /// <returns> /// The <see cref="object"/>. /// </returns> protected override object Deserialize(int num, object obj, ProtoReader protoReader) { switch (num) { case 0: return Read((MxMessage)obj, protoReader); case 1: return Read((MxPayload)obj, protoReader); default: return null; } }
public static DateTime ReadDateTime(ProtoReader source) { long num = BclHelpers.ReadTimeSpanTicks(source); if (num == -9223372036854775808L) { return DateTime.MinValue; } if (num == 9223372036854775807L) { return DateTime.MaxValue; } return BclHelpers.EpochOrigin.AddTicks(num); }
static public int ReadUInt16(IntPtr l) { try { ProtoBuf.ProtoReader self = (ProtoBuf.ProtoReader)checkSelf(l); var ret = self.ReadUInt16(); pushValue(l, true); pushValue(l, ret); return(2); } catch (Exception e) { return(error(l, e)); } }
static public int Assert(IntPtr l) { try { ProtoBuf.ProtoReader self = (ProtoBuf.ProtoReader)checkSelf(l); ProtoBuf.WireType a1; checkEnum(l, 2, out a1); self.Assert(a1); pushValue(l, true); return(1); } catch (Exception e) { return(error(l, e)); } }
static public int AppendExtensionData(IntPtr l) { try { ProtoBuf.ProtoReader self = (ProtoBuf.ProtoReader)checkSelf(l); ProtoBuf.IExtensible a1; checkType(l, 2, out a1); self.AppendExtensionData(a1); pushValue(l, true); return(1); } catch (Exception e) { return(error(l, e)); } }
static public int set_InternStrings(IntPtr l) { try { ProtoBuf.ProtoReader self = (ProtoBuf.ProtoReader)checkSelf(l); bool v; checkType(l, 2, out v); self.InternStrings = v; pushValue(l, true); return(1); } catch (Exception e) { return(error(l, e)); } }
/// <summary> /// The deserialize. /// </summary> /// <param name="num"> /// The num. /// </param> /// <param name="obj"> /// The obj. /// </param> /// <param name="protoReader"> /// The proto reader. /// </param> /// <returns> /// The <see cref="object"/>. /// </returns> protected override object Deserialize(int num, object obj, ProtoReader protoReader) { switch (num) { case 0: return Read((CompiledAsset)obj, protoReader); case 1: return Read((PlatformData)obj, protoReader); case 2: return _2(obj, protoReader); default: return null; } }
static public int TryReadFieldHeader(IntPtr l) { try { ProtoBuf.ProtoReader self = (ProtoBuf.ProtoReader)checkSelf(l); System.Int32 a1; checkType(l, 2, out a1); var ret = self.TryReadFieldHeader(a1); pushValue(l, true); pushValue(l, ret); return(2); } catch (Exception e) { return(error(l, e)); } }
static public int ThrowEnumException(IntPtr l) { try { ProtoBuf.ProtoReader self = (ProtoBuf.ProtoReader)checkSelf(l); System.Type a1; checkType(l, 2, out a1); System.Int32 a2; checkType(l, 3, out a2); self.ThrowEnumException(a1, a2); pushValue(l, true); return(1); } catch (Exception e) { return(error(l, e)); } }
public void TestRandomDataWithReader() { var input = File.ReadAllBytes("protobuf-net.dll"); var stream = new MemoryStream(input); stream.Seek(0, SeekOrigin.Begin); Assert.Greater(3, 0); // I always double-check the param order Assert.Greater(stream.Length, 0); using (var reader = new ProtoReader(stream, null, null)) { while (reader.ReadFieldHeader() > 0) { reader.SkipField(); } } }
// Use this for initialization void Start() { InitData(data); InitData(data2); InitData(data3); InitData(data4); msSend = new MemoryStream(sendBuffer, 0, SENF_BUFFER_LEN, true, true); msRecive = new MemoryStream(reciveBuffer, 0, REVIVE_BUFFER_LEN, true, true); bwWriter = new BinaryWriter(msSend); bwReader = new BinaryReader(msRecive); // ********只是为了测试,外部最好不要直接使用ProtoWriter和ProtoReader pbWriter = new ProtoBuf.ProtoWriter(msSend, ProtoBuf.Meta.RuntimeTypeModel.Default, null); pbReader = new ProtoBuf.ProtoReader(msRecive, ProtoBuf.Meta.RuntimeTypeModel.Default, null); pbWriter2 = new ProtoBuf.ProtoWriter(msSend, ProtoBuf.Meta.RuntimeTypeModel.Default, null); pbReader2 = new ProtoBuf.ProtoReader(msRecive, ProtoBuf.Meta.RuntimeTypeModel.Default, null); }
static public int constructor(IntPtr l) { try { int argc = LuaDLL.lua_gettop(l); ProtoBuf.ProtoReader o; if (argc == 4) { System.IO.Stream a1; checkType(l, 2, out a1); ProtoBuf.Meta.TypeModel a2; checkType(l, 3, out a2); ProtoBuf.SerializationContext a3; checkType(l, 4, out a3); o = new ProtoBuf.ProtoReader(a1, a2, a3); pushValue(l, true); pushValue(l, o); return(2); } else if (argc == 5) { System.IO.Stream a1; checkType(l, 2, out a1); ProtoBuf.Meta.TypeModel a2; checkType(l, 3, out a2); ProtoBuf.SerializationContext a3; checkType(l, 4, out a3); System.Int32 a4; checkType(l, 5, out a4); o = new ProtoBuf.ProtoReader(a1, a2, a3, a4); pushValue(l, true); pushValue(l, o); return(2); } return(error(l, "New object failed.")); } catch (Exception e) { return(error(l, e)); } }
public static decimal ReadDecimal(ProtoReader reader) { ulong num = 0uL; uint num2 = 0u; uint num3 = 0u; SubItemToken token = ProtoReader.StartSubItem(reader); int num4; while ((num4 = reader.ReadFieldHeader()) > 0) { switch (num4) { case 1: num = reader.ReadUInt64(); break; case 2: num2 = reader.ReadUInt32(); break; case 3: num3 = reader.ReadUInt32(); break; default: reader.SkipField(); break; } } ProtoReader.EndSubItem(token, reader); if (num == 0uL && num2 == 0u) { return 0m; } int lo = (int)(num & 0xFFFFFFFFL); int mid = (int)(num >> 32 & 0xFFFFFFFFL); int hi = (int)num2; bool isNegative = (num3 & 1u) == 1u; byte scale = (byte)((num3 & 510u) >> 1); return new decimal(lo, mid, hi, isNegative, scale); }
/// <summary>Indicates the number of bytes expected for the next message.</summary> /// <param name="source">The stream containing the data to investigate for a length.</param> /// <param name="style">The algorithm used to encode the length.</param> /// <param name="length">The length of the message, if it could be identified.</param> /// <returns>True if a length could be obtained, false otherwise.</returns> public static bool TryReadLengthPrefix(Stream source, PrefixStyle style, out int length) { length = ProtoReader.ReadLengthPrefix(source, false, style, out int _, out int bytesRead); return(bytesRead > 0); }
object ReadField(ProtoReader reader, Type memberT, string sClassName, CLS_Environment environment) { if (memberT == typeof(int)) { return reader.ReadInt32(); } else if (memberT == typeof(uint)) { return reader.ReadUInt32(); } else if (memberT == typeof(bool)) { return reader.ReadBoolean(); } else if (memberT == typeof(byte)) { return reader.ReadByte(); } else if (memberT == typeof(sbyte)) { return reader.ReadSByte(); } else if (memberT == typeof(float)) { return reader.ReadSingle(); } else if (memberT == typeof(double)) { return reader.ReadDouble(); } else if (memberT == typeof(short)) { return reader.ReadInt16(); } else if (memberT == typeof(ushort)) { return reader.ReadUInt16(); } else if (memberT == typeof(long)) { return reader.ReadInt64(); } else if (memberT == typeof(ulong)) { return reader.ReadUInt64(); } else if (memberT == typeof(string)) { return reader.ReadString(); } else if (memberT == typeof(byte[])) { return ProtoReader.AppendBytes(null, reader); } else if (memberT == typeof(SInstance)) { SubItemToken st = ProtoReader.StartSubItem(reader); CLS_Type_Class sClass = environment.GetTypeByKeywordQuiet(sClassName) as CLS_Type_Class; if (!sClass.compiled) RuntimeCompilerClass(sClassName); CLS_Content content = CLS_Content.NewContent(environment); CLS_Content.Value retVal = sClass.function.New(content, m_emptyParams); CLS_Content.PoolContent(content); SInstance sInstance = (SInstance)retVal.value; ReadSInstance(reader, sInstance, environment); ProtoReader.EndSubItem(st, reader); return sInstance; } else { throw new NotImplementedException("未实现类型: " + memberT); } }
/// <summary> /// Reads (merges) a sub-message from the stream, internally calling StartSubItem and EndSubItem, and (in between) /// parsing the message in accordance with the model associated with the reader /// </summary> public static object ReadObject(object value, int key, ProtoReader reader) { if (reader.model == null) { throw AddErrorData(new InvalidOperationException("Cannot deserialize sub-objects unless a model is provided"), reader); } SubItemToken token = ProtoReader.StartSubItem(reader); value = reader.model.Deserialize(key, value, reader); ProtoReader.EndSubItem(token, reader); return value; }
object BuildBody( uint realEMsg, Stream str ) { EMsg eMsg = MsgUtil.GetMsg( realEMsg ); if ( eMsg == EMsg.ClientLogonGameServer ) eMsg = EMsg.ClientLogon; // temp hack for now else if( eMsg == EMsg.ClientGamesPlayedWithDataBlob) eMsg = EMsg.ClientGamesPlayed; var protomsgType = typeof(CMClient).Assembly.GetTypes().ToList().Find(type => { if (type.GetInterfaces().ToList().Find(inter => inter == typeof(IExtensible)) == null) return false; if (type.Name.EndsWith(eMsg.ToString(), StringComparison.OrdinalIgnoreCase)) return true; return false; }); if (protomsgType != null) { return RuntimeTypeModel.Default.Deserialize(str, null, protomsgType); } // lets first find the type by checking all EMsgs we have var msgType = typeof( CMClient ).Assembly.GetTypes().ToList().Find( type => { if ( type.GetInterfaces().ToList().Find( inter => inter == typeof( ISteamSerializableMessage ) ) == null ) return false; var gcMsg = Activator.CreateInstance( type ) as ISteamSerializableMessage; return gcMsg.GetEMsg() == eMsg; } ); string eMsgName = eMsg.ToString(); eMsgName = eMsgName.Replace( "Econ", "" ).Replace( "AM", "" ); // check name if ( msgType == null ) msgType = GetSteamKitType( string.Format( "SteamKit2.Msg{0}", eMsgName ) ); if ( msgType != null ) { var body = Activator.CreateInstance( msgType ) as ISteamSerializableMessage; body.Deserialize( str ); return body; } msgType = GetSteamKitType( string.Format( "SteamKit2.CMsg{0}", eMsgName ) ); if ( msgType != null ) { return Deserialize( msgType, str ); } if ( eMsg == EMsg.ClientToGC || eMsg == EMsg.ClientFromGC ) { return Serializer.Deserialize<CMsgGCClient>( str ); } var gcMsgName = BuildEMsg( realEMsg ); var gcMsgPossibleTypePrefixes = new[] { "SteamKit2.GC.Internal.CMsg", "SteamKit2.GC.Dota.Internal.CMsg", "SteamKit2.GC.CSGO.Internal.CMsg", "SteamKit2.GC.TF.Internal.CMsg", }; var typeMsgName = gcMsgName .Replace("GC", string.Empty) .Replace("k_", string.Empty) .Replace("ESOMsg", string.Empty) .TrimStart('_') .Replace("EMsg", string.Empty); if ( typeMsgName == "Create" || typeMsgName == "Destroy" || typeMsgName == "Update" ) typeMsgName = "SingleObject"; else if ( typeMsgName == "Multiple" ) typeMsgName = "MultipleObjects"; var possibleTypes = from type in typeof( CMClient ).Assembly.GetTypes() from typePrefix in gcMsgPossibleTypePrefixes where type.GetInterfaces().Contains( typeof ( IExtensible ) ) where type.FullName.StartsWith( typePrefix ) && type.FullName.EndsWith( typeMsgName ) select type; foreach ( var type in possibleTypes ) { var streamPos = str.Position; try { return Deserialize( type, str ); } catch ( Exception ) { str.Position = streamPos; } } if (!MsgUtil.IsProtoBuf(realEMsg)) return null; // try reading it as a protobuf using (ProtoReader reader = new ProtoReader(str, null, null)) { var fields = new Dictionary<int, List<object>>(); while(true) { int field = reader.ReadFieldHeader(); if(field == 0) break; object fieldValue = null; switch (reader.WireType) { case WireType.Variant: case WireType.Fixed32: case WireType.Fixed64: case WireType.SignedVariant: { try { fieldValue = reader.ReadInt64(); } catch (Exception) { fieldValue = "Unable to read Variant (debugme)"; } break; } case WireType.String: { try { fieldValue = reader.ReadString(); } catch (Exception) { fieldValue = "Unable to read String (debugme)"; } break; } default: { fieldValue = string.Format( "{0} is not implemented", reader.WireType ); break; } } if ( !fields.ContainsKey( field ) ) { fields[ field ] = new List<object>(); } fields[ field ].Add( fieldValue ); } if (fields.Count > 0) return fields; } return null; }
/// <summary> /// Parses a TimeSpan from a protobuf stream /// </summary> public static TimeSpan ReadTimeSpan(ProtoReader source) { DateTimeKind kind; long ticks = ReadTimeSpanTicks(source, out kind); if (ticks == long.MinValue) return TimeSpan.MinValue; if (ticks == long.MaxValue) return TimeSpan.MaxValue; return TimeSpan.FromTicks(ticks); }
/// <summary> /// Reads an *implementation specific* bundled .NET object, including (as options) type-metadata, identity/re-use, etc. /// </summary> public static object ReadNetObject(object value, ProtoReader source, int key, Type type, NetObjectOptions options) { SubItemToken token = ProtoReader.StartSubItem(source); int fieldNumber; int newObjectKey = -1, newTypeKey = -1, tmp; while ((fieldNumber = source.ReadFieldHeader()) > 0) { switch (fieldNumber) { case FieldExistingObjectKey: tmp = source.ReadInt32(); value = source.NetCache.GetKeyedObject(tmp); break; case FieldNewObjectKey: newObjectKey = source.ReadInt32(); break; case FieldExistingTypeKey: tmp = source.ReadInt32(); type = (Type)source.NetCache.GetKeyedObject(tmp); key = source.GetTypeKey(ref type); break; case FieldNewTypeKey: newTypeKey = source.ReadInt32(); break; case FieldTypeName: type = source.DeserializeType(source.ReadString()); key = source.GetTypeKey(ref type); break; case FieldObject: bool isString = type == typeof(string); bool lateSet = value == null && isString; if (value == null && !lateSet) { value = ((options & NetObjectOptions.UseConstructor) == 0) ? BclHelpers.GetUninitializedObject(type) : Activator.CreateInstance(type); } if (newObjectKey >= 0 && !lateSet) { source.NetCache.SetKeyedObject(newObjectKey, value); if (newTypeKey >= 0) source.NetCache.SetKeyedObject(newTypeKey, type); } object oldValue = value; if (isString) { value = source.ReadString(); } else { value = ProtoReader.ReadTypedObject(oldValue, key, source, type); } if (newObjectKey >= 0 && lateSet) { source.NetCache.SetKeyedObject(newObjectKey, value); if (newTypeKey >= 0) source.NetCache.SetKeyedObject(newTypeKey, type); } if (!lateSet && !ReferenceEquals(oldValue, value)) { throw new ProtoException("A reference-tracked object changed reference during deserialization"); } break; default: source.SkipField(); break; } } ProtoReader.EndSubItem(token, source); return value; }
private static Exception EoF(ProtoReader source) { return(AddErrorData(new EndOfStreamException(), source)); }
public static Guid ReadGuid(ProtoReader source) { ulong num = 0uL; ulong num2 = 0uL; SubItemToken token = ProtoReader.StartSubItem(source); int num3; while ((num3 = source.ReadFieldHeader()) > 0) { int num4 = num3; if (num4 != 1) { if (num4 != 2) { source.SkipField(); } else { num2 = source.ReadUInt64(); } } else { num = source.ReadUInt64(); } } ProtoReader.EndSubItem(token, source); if (num == 0uL && num2 == 0uL) { return Guid.Empty; } uint num5 = (uint)(num >> 32); uint a = (uint)num; uint num6 = (uint)(num2 >> 32); uint num7 = (uint)num2; return new Guid((int)a, (short)num5, (short)(num5 >> 16), (byte)num7, (byte)(num7 >> 8), (byte)(num7 >> 16), (byte)(num7 >> 24), (byte)num6, (byte)(num6 >> 8), (byte)(num6 >> 16), (byte)(num6 >> 24)); }
private static long ReadTimeSpanTicks(ProtoReader source) { switch (source.WireType) { case WireType.Fixed64: return source.ReadInt64(); case WireType.String: case WireType.StartGroup: { SubItemToken token = ProtoReader.StartSubItem(source); TimeSpanScale timeSpanScale = TimeSpanScale.Days; long num = 0L; int num2; while ((num2 = source.ReadFieldHeader()) > 0) { int num3 = num2; if (num3 != 1) { if (num3 != 2) { source.SkipField(); } else { timeSpanScale = (TimeSpanScale)source.ReadInt32(); } } else { source.Assert(WireType.SignedVariant); num = source.ReadInt64(); } } ProtoReader.EndSubItem(token, source); TimeSpanScale timeSpanScale2 = timeSpanScale; switch (timeSpanScale2) { case TimeSpanScale.Days: return num * 864000000000L; case TimeSpanScale.Hours: return num * 36000000000L; case TimeSpanScale.Minutes: return num * 600000000L; case TimeSpanScale.Seconds: return num * 10000000L; case TimeSpanScale.Milliseconds: return num * 10000L; case TimeSpanScale.Ticks: return num; default: { if (timeSpanScale2 != TimeSpanScale.MinMax) { throw new ProtoException("Unknown timescale: " + timeSpanScale.ToString()); } long num4 = num; if (num4 >= -1L && num4 <= 1L) { switch ((int)(num4 - -1L)) { case 0: return -9223372036854775808L; case 2: return 9223372036854775807L; } } throw new ProtoException("Unknown min/max value: " + num.ToString()); } } break; } default: throw new ProtoException("Unexpected wire-type: " + source.WireType.ToString()); } }
public static decimal ReadDecimal(ProtoReader reader) { ProtoReader.State state = default; return(ReadDecimal(reader, ref state)); }
public static TimeSpan ReadTimeSpan(ProtoReader source) { long num = BclHelpers.ReadTimeSpanTicks(source); if (num == -9223372036854775808L) { return TimeSpan.MinValue; } if (num == 9223372036854775807L) { return TimeSpan.MaxValue; } return TimeSpan.FromTicks(num); }
public static object ReadNetObject(object value, ProtoReader source, int key, Type type, BclHelpers.NetObjectOptions options) { SubItemToken token = ProtoReader.StartSubItem(source); int num = -1; int num2 = -1; int num3; while ((num3 = source.ReadFieldHeader()) > 0) { switch (num3) { case 1: { int key2 = source.ReadInt32(); value = source.NetCache.GetKeyedObject(key2); continue; } case 2: num = source.ReadInt32(); continue; case 3: { int key2 = source.ReadInt32(); type = (Type)source.NetCache.GetKeyedObject(key2); key = source.GetTypeKey(ref type); continue; } case 4: num2 = source.ReadInt32(); continue; case 8: { string text = source.ReadString(); type = source.DeserializeType(text); if (type == null) { throw new ProtoException("Unable to resolve type: " + text + " (you can use the TypeModel.DynamicTypeFormatting event to provide a custom mapping)"); } if (type == typeof(string)) { key = -1; } else { key = source.GetTypeKey(ref type); if (key < 0) { throw new InvalidOperationException("Dynamic type is not a contract-type: " + type.Name); } } continue; } case 10: { bool flag = type == typeof(string); bool flag2 = value == null; bool flag3 = flag2 && (flag || (byte)(options & BclHelpers.NetObjectOptions.LateSet) != 0); if (num >= 0 && !flag3) { if (value == null) { source.TrapNextObject(num); } else { source.NetCache.SetKeyedObject(num, value); } if (num2 >= 0) { source.NetCache.SetKeyedObject(num2, type); } } object obj = value; if (flag) { value = source.ReadString(); } else { value = ProtoReader.ReadTypedObject(obj, key, source, type); } if (num >= 0) { if (flag2 && !flag3) { obj = source.NetCache.GetKeyedObject(num); } if (flag3) { source.NetCache.SetKeyedObject(num, value); if (num2 >= 0) { source.NetCache.SetKeyedObject(num2, type); } } } if (num >= 0 && !flag3 && !object.ReferenceEquals(obj, value)) { throw new ProtoException("A reference-tracked object changed reference during deserialization"); } if (num < 0 && num2 >= 0) { source.NetCache.SetKeyedObject(num2, type); } continue; } } source.SkipField(); } if (num >= 0 && (byte)(options & BclHelpers.NetObjectOptions.AsReference) == 0) { throw new ProtoException("Object key in input stream, but reference-tracking was not expected"); } ProtoReader.EndSubItem(token, source); return value; }
void ReadSInstance(ProtoReader reader, SInstance sInstance, CLS_Environment environment) { List<CLS_Content.Value> values; List<string> keywords; GetSortMembers(sInstance, out values, out keywords); int fieldNumber = 0; while ((fieldNumber = reader.ReadFieldHeader()) > 0) { Type memberT = values[fieldNumber - 1].type; CLS_Content.Value memberV = values[fieldNumber - 1]; string sClassName = keywords[fieldNumber - 1]; if (memberT == null) { memberT = typeof(SInstance); sClassName = ((SType)memberV.type).Name; } Type itemType = GetItemType(memberT); if (itemType != null) { sClassName = sInstance.type.members[sClassName].type.keyword; // 数组判断 if (memberT.IsArray) { string itemClass = sClassName.Substring(0, sClassName.Length - 2); // 从 xxx[] 中提取xxx BasicList list = new BasicList(); do { list.Add(ReadField(reader, itemType, itemClass, environment)); } while (reader.TryReadFieldHeader(fieldNumber)); Array result = Array.CreateInstance(itemType, list.Count); list.CopyTo(result, 0); memberV.value = result; } // 列表判断 else { string itemClass = sClassName.Substring(5, sClassName.Length - 6); // 从 List<xxx> 中提取xxx ICLS_Type iType = environment.GetTypeByKeywordQuiet(sClassName); CLS_Content content = CLS_Content.NewContent(environment); memberV.value = iType.function.New(content, m_emptyParams).value; CLS_Content.PoolContent(content); IList list = (IList)memberV.value; do { list.Add(ReadField(reader, itemType, itemClass, environment)); } while (reader.TryReadFieldHeader(fieldNumber)); } } else { memberV.value = ReadField(reader, memberT, sClassName, environment); } } }
/// <summary> /// Reads an *implementation specific* bundled .NET object, including (as options) type-metadata, identity/re-use, etc. /// </summary> public static object ReadNetObject(object value, ProtoReader source, int key, Type type, NetObjectOptions options) { SubItemToken token = ProtoReader.StartSubItem(source); int fieldNumber; int newObjectKey = -1, newTypeKey = -1, tmp; while ((fieldNumber = source.ReadFieldHeader()) > 0) { switch (fieldNumber) { case FieldExistingObjectKey: tmp = source.ReadInt32(); value = source.NetCache.GetKeyedObject(tmp); break; case FieldNewObjectKey: newObjectKey = source.ReadInt32(); break; case FieldExistingTypeKey: tmp = source.ReadInt32(); type = (Type)source.NetCache.GetKeyedObject(tmp); key = source.GetTypeKey(ref type); break; case FieldNewTypeKey: newTypeKey = source.ReadInt32(); break; case FieldTypeName: type = source.DeserializeType(source.ReadString()); key = source.GetTypeKey(ref type); break; case FieldObject: bool isString = type == typeof(string); bool lateSet = value == null && isString; if (value == null && !lateSet) { value = ((options & NetObjectOptions.UseConstructor) == 0) ? BclHelpers.GetUninitializedObject(type) : Activator.CreateInstance(type); } if (newObjectKey >= 0 && !lateSet) { source.NetCache.SetKeyedObject(newObjectKey, value); if (newTypeKey >= 0) { source.NetCache.SetKeyedObject(newTypeKey, type); } } object oldValue = value; if (isString) { value = source.ReadString(); } else { value = ProtoReader.ReadTypedObject(oldValue, key, source, type); } if (newObjectKey >= 0 && lateSet) { source.NetCache.SetKeyedObject(newObjectKey, value); if (newTypeKey >= 0) { source.NetCache.SetKeyedObject(newTypeKey, type); } } if (!lateSet && !ReferenceEquals(oldValue, value)) { throw new ProtoException("A reference-tracked object changed reference during deserialization"); } break; default: source.SkipField(); break; } } ProtoReader.EndSubItem(token, source); return(value); }
/// <summary> /// Reads an *implementation specific* bundled .NET object, including (as options) type-metadata, identity/re-use, etc. /// </summary> public static object ReadNetObject(object value, ProtoReader source, int key, Type type, NetObjectOptions options) { #if FEAT_IKVM throw new NotSupportedException(); #else SubItemToken token = ProtoReader.StartSubItem(source); int fieldNumber; int newObjectKey = -1, newTypeKey = -1, tmp; while ((fieldNumber = source.ReadFieldHeader()) > 0) { switch (fieldNumber) { case FieldExistingObjectKey: tmp = source.ReadInt32(); value = source.NetCache.GetKeyedObject(tmp); break; case FieldNewObjectKey: newObjectKey = source.ReadInt32(); break; case FieldExistingTypeKey: tmp = source.ReadInt32(); type = (Type)source.NetCache.GetKeyedObject(tmp); key = source.GetTypeKey(ref type); break; case FieldNewTypeKey: newTypeKey = source.ReadInt32(); break; case FieldTypeName: string typeName = source.ReadString(); type = source.DeserializeType(typeName); if (type == null) { throw new ProtoException("Unable to resolve type: " + typeName + " (you can use the TypeModel.DynamicTypeFormatting event to provide a custom mapping)"); } if (type == typeof(string)) { key = -1; } else { key = source.GetTypeKey(ref type); if (key < 0) { throw new InvalidOperationException("Dynamic type is not a contract-type: " + type.Name); } } break; case FieldObject: bool isString = type == typeof(string); bool wasNull = value == null; bool lateSet = wasNull && (isString || ((options & NetObjectOptions.LateSet) != 0)); if (newObjectKey >= 0 && !lateSet) { if (value == null) { source.TrapNextObject(newObjectKey); } else { source.NetCache.SetKeyedObject(newObjectKey, value); } if (newTypeKey >= 0) { source.NetCache.SetKeyedObject(newTypeKey, type); } } object oldValue = value; if (isString) { value = source.ReadString(); } else { value = ProtoReader.ReadTypedObject(oldValue, key, source, type); } if (newObjectKey >= 0) { if (wasNull && !lateSet) { // this both ensures (via exception) that it *was* set, and makes sure we don't shout // about changed references oldValue = source.NetCache.GetKeyedObject(newObjectKey); } if (lateSet) { source.NetCache.SetKeyedObject(newObjectKey, value); if (newTypeKey >= 0) { source.NetCache.SetKeyedObject(newTypeKey, type); } } } if (newObjectKey >= 0 && !lateSet && !ReferenceEquals(oldValue, value)) { throw new ProtoException("A reference-tracked object changed reference during deserialization"); } if (newObjectKey < 0 && newTypeKey >= 0) { // have a new type, but not a new object source.NetCache.SetKeyedObject(newTypeKey, type); } break; default: source.SkipField(); break; } } if (newObjectKey >= 0 && (options & NetObjectOptions.AsReference) == 0) { throw new ProtoException("Object key in input stream, but reference-tracking was not expected"); } ProtoReader.EndSubItem(token, source); return(value); #endif }
public static object ReadObject(object value, int key, ProtoReader reader) { return(ReadTypedObject(value, key, reader, null)); }
/// <summary> /// Begins consuming a nested message in the stream; supported wire-types: StartGroup, String /// </summary> /// <remarks>The token returned must be help and used when callining EndSubItem</remarks> public static SubItemToken StartSubItem(ProtoReader reader) { switch (reader.wireType) { case WireType.StartGroup: reader.wireType = WireType.None; // to prevent glitches from double-calling reader.depth++; return new SubItemToken(-reader.fieldNumber); case WireType.String: int len = (int)reader.ReadUInt32Variant(false); if (len < 0) throw AddErrorData(new InvalidOperationException(), reader); int lastEnd = reader.blockEnd; reader.blockEnd = reader.position + len; reader.depth++; return new SubItemToken(lastEnd); default: throw reader.CreateException(); // throws } }
protected internal override object DeserializeCore(ProtoReader source, ref ProtoReader.State state, int key, object value) => null;
internal static Exception AddErrorData(Exception exception, ProtoReader source) { #if !CF if (exception != null && source != null && !exception.Data.Contains("protoSource")) { exception.Data.Add("protoSource", string.Format("tag={0}; wire-type={1}; offset={2}; depth={3}", source.fieldNumber, source.wireType, source.position, source.depth)); } #endif return exception; }
/// <summary> /// All this does is call GetExtendedValuesTyped with the correct type for "instance"; /// this ensures that we don't get issues with subclasses declaring conflicting types - /// the caller must respect the fields defined for the type they pass in. /// </summary> internal static IEnumerable GetExtendedValues(TypeModel model, Type type, IExtensible instance, int tag, byte format, bool singleton, bool allowDefinedTag) { #if FEAT_IKVM throw new NotSupportedException(); #else if (instance == null) { throw new ArgumentNullException("instance"); } if (tag <= 0) { throw new ArgumentOutOfRangeException("tag"); } IExtension extn = instance.GetExtensionObject(false); if (extn == null) { #if FX11 return(new object[0]); #else yield break; #endif } #if FX11 BasicList result = new BasicList(); #endif Stream stream = extn.BeginQuery(); object value = null; ProtoReader reader = null; try { SerializationContext ctx = new SerializationContext(); reader = ProtoReader.Create(stream, model, ctx, ProtoReader.TO_EOF); while (model.TryDeserializeAuxiliaryType(reader, format, tag, type, ref value, true, false, false, false) && value != null) { if (!singleton) { #if FX11 result.Add(value); #else yield return(value); #endif value = null; // fresh item each time } } if (singleton && value != null) { #if FX11 result.Add(value); #else yield return(value); #endif } #if FX11 object[] resultArr = new object[result.Count]; result.CopyTo(resultArr, 0); return(resultArr); #endif } finally { ProtoReader.Recycle(reader); extn.EndQuery(stream); } #endif }
private static long ReadTimeSpanTicks(ProtoReader source) { switch (source.WireType) { case WireType.String: case WireType.StartGroup: SubItemToken token = ProtoReader.StartSubItem(source); int fieldNumber; TimeSpanScale scale = TimeSpanScale.Days; long value = 0; while ((fieldNumber = source.ReadFieldHeader()) > 0) { switch (fieldNumber) { case FieldTimeSpanScale: scale = (TimeSpanScale)source.ReadInt32(); break; case FieldTimeSpanValue: source.Assert(WireType.SignedVariant); value = source.ReadInt64(); break; default: source.SkipField(); break; } } ProtoReader.EndSubItem(token, source); switch (scale) { case TimeSpanScale.Days: return(value * TimeSpan.TicksPerDay); case TimeSpanScale.Hours: return(value * TimeSpan.TicksPerHour); case TimeSpanScale.Minutes: return(value * TimeSpan.TicksPerMinute); case TimeSpanScale.Seconds: return(value * TimeSpan.TicksPerSecond); case TimeSpanScale.Milliseconds: return(value * TimeSpan.TicksPerMillisecond); case TimeSpanScale.Ticks: return(value); case TimeSpanScale.MinMax: switch (value) { case 1: return(long.MaxValue); case -1: return(long.MinValue); default: throw new ProtoException("Unknown min/max value: " + value.ToString()); } default: throw new ProtoException("Unknown timescale: " + scale.ToString()); } case WireType.Fixed64: return(source.ReadInt64()); default: throw new ProtoException("Unexpected wire-type: " + source.WireType.ToString()); } }
/// <summary> /// Parses a DateTime from a protobuf stream /// </summary> public static DateTime ReadDateTime(ProtoReader source) { DateTimeKind kind; long ticks = ReadTimeSpanTicks(source, out kind); if (ticks == long.MinValue) return DateTime.MinValue; if (ticks == long.MaxValue) return DateTime.MaxValue; return EpochOrigin[(int)kind].AddTicks(ticks); }
/// <summary> /// Parses a TimeSpan from a protobuf stream /// </summary> public static TimeSpan ReadTimeSpan(ProtoReader source) { long ticks = ReadTimeSpanTicks(source); if (ticks == long.MinValue) return TimeSpan.MinValue; if (ticks == long.MaxValue) return TimeSpan.MaxValue; return TimeSpan.FromTicks(ticks); }
/// <summary> /// Indicates whether the reader still has data remaining in the current sub-item, /// additionally setting the wire-type for the next field if there is more data. /// This is used when decoding packed data. /// </summary> public static bool HasSubValue(ProtoBuf.WireType wireType, ProtoReader source) { // check for virtual end of stream if (source.blockEnd <= source.position || wireType == WireType.EndGroup) { return false; } source.wireType = wireType; return true; }
private static long ReadTimeSpanTicks(ProtoReader source) { switch (source.WireType) { case WireType.String: case WireType.StartGroup: SubItemToken token = ProtoReader.StartSubItem(source); int fieldNumber; TimeSpanScale scale = TimeSpanScale.Days; long value = 0; while ((fieldNumber = source.ReadFieldHeader()) > 0) { switch (fieldNumber) { case FieldTimeSpanScale: scale = (TimeSpanScale)source.ReadInt32(); break; case FieldTimeSpanValue: source.Assert(WireType.SignedVariant); value = source.ReadInt64(); break; default: source.SkipField(); break; } } ProtoReader.EndSubItem(token, source); switch (scale) { case TimeSpanScale.Days: return value * TimeSpan.TicksPerDay; case TimeSpanScale.Hours: return value * TimeSpan.TicksPerHour; case TimeSpanScale.Minutes: return value * TimeSpan.TicksPerMinute; case TimeSpanScale.Seconds: return value * TimeSpan.TicksPerSecond; case TimeSpanScale.Milliseconds: return value * TimeSpan.TicksPerMillisecond; case TimeSpanScale.Ticks: return value; case TimeSpanScale.MinMax: switch (value) { case 1: return long.MaxValue; case -1: return long.MinValue; default: throw new ProtoException("Unknown min/max value: " + value.ToString()); } default: throw new ProtoException("Unknown timescale: " + scale.ToString()); } case WireType.Fixed64: return source.ReadInt64(); default: throw new ProtoException("Unexpected wire-type: " + source.WireType.ToString()); } }
/// <summary> /// Makes the end of consuming a nested message in the stream; the stream must be either at the correct EndGroup /// marker, or all fields of the sub-message must have been consumed (in either case, this means ReadFieldHeader /// should return zero) /// </summary> public static void EndSubItem(SubItemToken token, ProtoReader reader) { int value = token.value; switch (reader.wireType) { case WireType.EndGroup: if (value >= 0) throw AddErrorData(new ArgumentException("token"), reader); if (-value != reader.fieldNumber) throw reader.CreateException(); // wrong group ended! reader.wireType = WireType.None; // this releases ReadFieldHeader reader.depth--; break; // case WireType.None: // TODO reinstate once reads reset the wire-type default: if (value < reader.position) throw reader.CreateException(); if (reader.blockEnd != reader.position && reader.blockEnd != int.MaxValue) throw reader.CreateException(); reader.blockEnd = value; reader.depth--; break; /*default: throw reader.BorkedIt(); */ } }
private static long ReadTimeSpanTicks(ProtoReader source) { switch (source.WireType) { case WireType.String: case WireType.StartGroup: { SubItemToken token = ProtoReader.StartSubItem(source); TimeSpanScale timeSpanScale = TimeSpanScale.Days; long num = 0L; int num2; while ((num2 = source.ReadFieldHeader()) > 0) { switch (num2) { case 2: timeSpanScale = (TimeSpanScale)source.ReadInt32(); break; case 1: source.Assert(WireType.SignedVariant); num = source.ReadInt64(); break; default: source.SkipField(); break; } } ProtoReader.EndSubItem(token, source); switch (timeSpanScale) { case TimeSpanScale.Days: return(num * 864000000000L); case TimeSpanScale.Hours: return(num * 36000000000L); case TimeSpanScale.Minutes: return(num * 600000000); case TimeSpanScale.Seconds: return(num * 10000000); case TimeSpanScale.Milliseconds: return(num * 10000); case TimeSpanScale.Ticks: return(num); case TimeSpanScale.MinMax: switch (num) { case 1L: return(long.MaxValue); case -1L: return(long.MinValue); default: throw new ProtoException("Unknown min/max value: " + num.ToString()); } default: throw new ProtoException("Unknown timescale: " + timeSpanScale.ToString()); } } case WireType.Fixed64: return(source.ReadInt64()); default: throw new ProtoException("Unexpected wire-type: " + source.WireType.ToString()); } }
/// <summary> /// Reads a byte-sequence from the stream, appending them to an existing byte-sequence (which can be null); supported wire-types: String /// </summary> public static byte[] AppendBytes(byte[] value, ProtoReader reader) { switch (reader.wireType) { case WireType.String: int len = (int)reader.ReadUInt32Variant(false); reader.wireType = WireType.None; if (len == 0) return value; int offset; if(value == null || value.Length == 0) { offset = 0; value = new byte[len]; } else { offset = value.Length; byte[] tmp = new byte[value.Length + len]; Helpers.BlockCopy(value, 0, tmp, 0, value.Length); value = tmp; } // value is now sized with the final length, and (if necessary) // contains the old data up to "offset" reader.position += len; // assume success while (len > reader.available) { if (reader.available > 0) { // copy what we *do* have Helpers.BlockCopy(reader.ioBuffer, reader.ioIndex, value, offset, reader.available); len -= reader.available; offset += reader.available; reader.ioIndex = reader.available = 0; // we've drained the buffer } // now refill the buffer (without overflowing it) int count = len > reader.ioBuffer.Length ? reader.ioBuffer.Length : len; if (count > 0) reader.Ensure(count, true); } // at this point, we know that len <= available if (len > 0) { // still need data, but we have enough buffered Helpers.BlockCopy(reader.ioBuffer, reader.ioIndex, value, offset, len); reader.ioIndex += len; reader.available -= len; } return value; default: throw reader.CreateException(); } }
/// <summary> /// Parses a Guid from a protobuf stream /// </summary> public static Guid ReadGuid(ProtoReader source) { ulong low = 0, high = 0; int fieldNumber; SubItemToken token = ProtoReader.StartSubItem(source); while ((fieldNumber = source.ReadFieldHeader()) > 0) { switch (fieldNumber) { case FieldGuidLow: low = source.ReadUInt64(); break; case FieldGuidHigh: high = source.ReadUInt64(); break; default: source.SkipField(); break; } } ProtoReader.EndSubItem(token, source); if(low == 0 && high == 0) return Guid.Empty; uint a = (uint)(low >> 32), b = (uint)low, c = (uint)(high >> 32), d= (uint)high; return new Guid((int)b, (short)a, (short)(a >> 16), (byte)d, (byte)(d >> 8), (byte)(d >> 16), (byte)(d >> 24), (byte)c, (byte)(c >> 8), (byte)(c >> 16), (byte)(c >> 24)); }
private static Exception EoF(ProtoReader source) { return AddErrorData(new EndOfStreamException(), source); }
// Token: 0x06000039 RID: 57 RVA: 0x0000A274 File Offset: 0x00008474 private static long ReadTimeSpanTicks(ProtoReader source) { WireType wireType = source.WireType; if (wireType == WireType.Fixed64) { return(source.ReadInt64()); } if (wireType - WireType.String > 1) { throw new ProtoException("Unexpected wire-type: " + source.WireType.ToString()); } SubItemToken token = ProtoReader.StartSubItem(source); TimeSpanScale timeSpanScale = TimeSpanScale.Days; long num = 0L; int num2; while ((num2 = source.ReadFieldHeader()) > 0) { if (num2 != 1) { if (num2 == 2) { timeSpanScale = (TimeSpanScale)source.ReadInt32(); } else { source.SkipField(); } } else { source.Assert(WireType.SignedVariant); num = source.ReadInt64(); } } ProtoReader.EndSubItem(token, source); switch (timeSpanScale) { case TimeSpanScale.Days: return(num * 864000000000L); case TimeSpanScale.Hours: return(num * 36000000000L); case TimeSpanScale.Minutes: return(num * 600000000L); case TimeSpanScale.Seconds: return(num * 10000000L); case TimeSpanScale.Milliseconds: return(num * 10000L); case TimeSpanScale.Ticks: return(num); default: if (timeSpanScale != TimeSpanScale.MinMax) { throw new ProtoException("Unknown timescale: " + timeSpanScale.ToString()); } if (num == -1L) { return(long.MinValue); } if (num == 1L) { return(long.MaxValue); } throw new ProtoException("Unknown min/max value: " + num.ToString()); } }
/// <summary> /// Reads an *implementation specific* bundled .NET object, including (as options) type-metadata, identity/re-use, etc. /// </summary> public static object ReadNetObject(object value, ProtoReader source, int key, Type type, NetObjectOptions options) { SubItemToken token = ProtoReader.StartSubItem(source); int fieldNumber; int newObjectKey = -1, newTypeKey = -1, tmp; while ((fieldNumber = source.ReadFieldHeader()) > 0) { switch (fieldNumber) { case FieldExistingObjectKey: tmp = source.ReadInt32(); value = source.NetCache.GetKeyedObject(tmp); break; case FieldNewObjectKey: newObjectKey = source.ReadInt32(); break; case FieldExistingTypeKey: tmp = source.ReadInt32(); type = (Type)source.NetCache.GetKeyedObject(tmp); key = source.GetTypeKey(ref type); break; case FieldNewTypeKey: newTypeKey = source.ReadInt32(); break; case FieldTypeName: string typeName = source.ReadString(); type = source.DeserializeType(typeName); if(type == null) { throw new ProtoException("Unable to resolve type: " + typeName + " (you can use the TypeModel.DynamicTypeFormatting event to provide a custom mapping)"); } key = source.GetTypeKey(ref type); if(key < 0) throw new InvalidOperationException("Dynamic type is not a contract-type: " + type.Name); break; case FieldObject: bool isString = type == typeof(string); bool lateSet = value == null && isString; if (value == null && !lateSet) { try { value = ((options & NetObjectOptions.UseConstructor) == 0) ? BclHelpers.GetUninitializedObject(type) : (type.IsArray || type.IsInterface ? null : Activator.CreateInstance(type, true)); } catch (Exception ex) { throw new ProtoException("Unable to create type " + (type == null ? "<null>" : type.FullName) + ": " + ex.Message, ex); } } if (newObjectKey >= 0 && !lateSet) { source.NetCache.SetKeyedObject(newObjectKey, value); if (newTypeKey >= 0) source.NetCache.SetKeyedObject(newTypeKey, type); } object oldValue = value; if (isString) { value = source.ReadString(); } else { value = ProtoReader.ReadTypedObject(oldValue, key, source, type); } if (newObjectKey >= 0 && lateSet) { source.NetCache.SetKeyedObject(newObjectKey, value); if (newTypeKey >= 0) source.NetCache.SetKeyedObject(newTypeKey, type); } if (newObjectKey >= 0 && !lateSet && !ReferenceEquals(oldValue, value) && type.FullName.StartsWith("System.Collections.Generic.Dictionary`2")) { throw new ProtoException("A reference-tracked object changed reference during deserialization"); } if (newObjectKey < 0 && newTypeKey >= 0) { // have a new type, but not a new object source.NetCache.SetKeyedObject(newTypeKey, type); } break; default: source.SkipField(); break; } } if(newObjectKey >= 0 && (options & NetObjectOptions.AsReference) == 0) { throw new ProtoException("Object key in input stream, but reference-tracking was not expected"); } ProtoReader.EndSubItem(token, source); return value; }
public static DateTime ReadDateTime(ProtoReader source) { ProtoReader.State state = default; return(ReadDateTime(source, ref state)); }
/// <summary> /// Parses a DateTime from a protobuf stream /// </summary> public static DateTime ReadDateTime(ProtoReader source) { long ticks = ReadTimeSpanTicks(source); if (ticks == long.MinValue) return DateTime.MinValue; if (ticks == long.MaxValue) return DateTime.MaxValue; return EpochOrigin.AddTicks(ticks); }
public static TimeSpan ReadDuration(ProtoReader source) { ProtoReader.State state = default; return(ReadDuration(source, ref state)); }
/// <summary> /// Parses a decimal from a protobuf stream /// </summary> public static decimal ReadDecimal(ProtoReader reader) { ulong low = 0; uint high = 0; uint signScale = 0; int fieldNumber; SubItemToken token = ProtoReader.StartSubItem(reader); while ((fieldNumber = reader.ReadFieldHeader()) > 0) { switch (fieldNumber) { case FieldDecimalLow: low = reader.ReadUInt64(); break; case FieldDecimalHigh: high = reader.ReadUInt32(); break; case FieldDecimalSignScale: signScale = reader.ReadUInt32(); break; default: reader.SkipField(); break; } } ProtoReader.EndSubItem(token, reader); if (low == 0 && high == 0) return decimal.Zero; int lo = (int)(low & 0xFFFFFFFFL), mid = (int)((low >> 32) & 0xFFFFFFFFL), hi = (int)high; bool isNeg = (signScale & 0x0001) == 0x0001; byte scale = (byte)((signScale & 0x01FE) >> 1); return new decimal(lo, mid, hi, isNeg, scale); }
public static object ReadNetObject(object value, ProtoReader source, int key, Type type, NetObjectOptions options) { SubItemToken token = ProtoReader.StartSubItem(source); int num = -1; int num2 = -1; int num3; while ((num3 = source.ReadFieldHeader()) > 0) { switch (num3) { case 1: { int key2 = source.ReadInt32(); value = source.NetCache.GetKeyedObject(key2); break; } case 2: num = source.ReadInt32(); break; case 3: { int key2 = source.ReadInt32(); type = (Type)source.NetCache.GetKeyedObject(key2); key = source.GetTypeKey(ref type); break; } case 4: num2 = source.ReadInt32(); break; case 8: { string text = source.ReadString(); type = source.DeserializeType(text); if (type == null) { throw new ProtoException("Unable to resolve type: " + text + " (you can use the TypeModel.DynamicTypeFormatting event to provide a custom mapping)"); } if (type == typeof(string)) { key = -1; break; } key = source.GetTypeKey(ref type); if (key >= 0) { break; } throw new InvalidOperationException("Dynamic type is not a contract-type: " + type.Name); } case 10: { bool flag = type == typeof(string); bool flag2 = value == null; bool flag3 = flag2 && (flag || (options & NetObjectOptions.LateSet) != NetObjectOptions.None); if (num >= 0 && !flag3) { if (value == null) { source.TrapNextObject(num); } else { source.NetCache.SetKeyedObject(num, value); } if (num2 >= 0) { source.NetCache.SetKeyedObject(num2, type); } } object obj = value; value = ((!flag) ? ProtoReader.ReadTypedObject(obj, key, source, type) : source.ReadString()); if (num >= 0) { if (flag2 && !flag3) { obj = source.NetCache.GetKeyedObject(num); } if (flag3) { source.NetCache.SetKeyedObject(num, value); if (num2 >= 0) { source.NetCache.SetKeyedObject(num2, type); } } } if (num >= 0 && !flag3 && obj != value) { throw new ProtoException("A reference-tracked object changed reference during deserialization"); } if (num < 0 && num2 >= 0) { source.NetCache.SetKeyedObject(num2, type); } break; } default: source.SkipField(); break; } } if (num >= 0 && (options & NetObjectOptions.AsReference) == NetObjectOptions.None) { throw new ProtoException("Object key in input stream, but reference-tracking was not expected"); } ProtoReader.EndSubItem(token, source); return(value); }
/// <summary> /// Reads an *implementation specific* bundled .NET object, including (as options) type-metadata, identity/re-use, etc. /// </summary> public static object ReadNetObject(object value, ProtoReader source, int key, Type type, NetObjectOptions options) { #if FEAT_IKVM throw new NotSupportedException(); #else SubItemToken token = ProtoReader.StartSubItem(source); int fieldNumber; int newObjectKey = -1, newTypeKey = -1, tmp; while ((fieldNumber = source.ReadFieldHeader()) > 0) { switch (fieldNumber) { case FieldExistingObjectKey: tmp = source.ReadInt32(); value = source.NetCache.GetKeyedObject(tmp); break; case FieldNewObjectKey: newObjectKey = source.ReadInt32(); break; case FieldExistingTypeKey: tmp = source.ReadInt32(); type = (Type)source.NetCache.GetKeyedObject(tmp); key = source.GetTypeKey(ref type); break; case FieldNewTypeKey: newTypeKey = source.ReadInt32(); break; case FieldTypeName: string typeName = source.ReadString(); type = source.DeserializeType(typeName); if(type == null) { throw new ProtoException("Unable to resolve type: " + typeName + " (you can use the TypeModel.DynamicTypeFormatting event to provide a custom mapping)"); } if (type == typeof(string)) { key = -1; } else { key = source.GetTypeKey(ref type); if (key < 0) throw new InvalidOperationException("Dynamic type is not a contract-type: " + type.Name); } break; case FieldObject: bool isString = type == typeof(string); bool wasNull = value == null; bool lateSet = wasNull && (isString || ((options & NetObjectOptions.LateSet) != 0)); if (newObjectKey >= 0 && !lateSet) { if (value == null) { source.TrapNextObject(newObjectKey); } else { source.NetCache.SetKeyedObject(newObjectKey, value); } if (newTypeKey >= 0) source.NetCache.SetKeyedObject(newTypeKey, type); } object oldValue = value; if (isString) { value = source.ReadString(); } else { value = ProtoReader.ReadTypedObject(oldValue, key, source, type); } if (newObjectKey >= 0) { if(wasNull && !lateSet) { // this both ensures (via exception) that it *was* set, and makes sure we don't shout // about changed references oldValue = source.NetCache.GetKeyedObject(newObjectKey); } if (lateSet) { source.NetCache.SetKeyedObject(newObjectKey, value); if (newTypeKey >= 0) source.NetCache.SetKeyedObject(newTypeKey, type); } } if (newObjectKey >= 0 && !lateSet && !ReferenceEquals(oldValue, value)) { throw new ProtoException("A reference-tracked object changed reference during deserialization"); } if (newObjectKey < 0 && newTypeKey >= 0) { // have a new type, but not a new object source.NetCache.SetKeyedObject(newTypeKey, type); } break; default: source.SkipField(); break; } } if(newObjectKey >= 0 && (options & NetObjectOptions.AsReference) == 0) { throw new ProtoException("Object key in input stream, but reference-tracking was not expected"); } ProtoReader.EndSubItem(token, source); return value; #endif }
public static TimeSpan ReadTimeSpan(ProtoReader source) { ProtoReader.State state = source.DefaultState(); return(ReadTimeSpan(ref state)); }