using System; using System.Collections.Generic; using System.IO; using System.Text; using ProtoBuf.Meta; namespace ProtoBuf { public sealed class ProtoReader : IDisposable { public int FieldNumber { get { return this.fieldNumber; } } public WireType WireType { get { return this.wireType; } } public bool InternStrings { get { return this.internStrings; } set { this.internStrings = value; } } public SerializationContext Context { get { return this.context; } } public int Position { get { return this.position; } } public TypeModel Model { get { return this.model; } } internal NetObjectCache NetCache { get { return this.netCache; } } private Stream source; private byte[] ioBuffer; private TypeModel model; private int fieldNumber; private int depth; private int dataRemaining; private int ioIndex; private int position; private int available; private int blockEnd; private WireType wireType; private bool isFixedLength; private bool internStrings; private NetObjectCache netCache; private uint trapCount; internal const int TO_EOF = -1; private SerializationContext context; private const long Int64Msb = -9223372036854775808L; private const int Int32Msb = -2147483648; private Dictionary stringInterner; private static readonly UTF8Encoding encoding = new UTF8Encoding(); private static readonly byte[] EmptyBlob = new byte[0]; [ThreadStatic] private static ProtoReader lastReader; public ProtoReader(Stream source, TypeModel model, SerializationContext context) { ProtoReader.Init(this, source, model, context, -1); } public ProtoReader(Stream source, TypeModel model, SerializationContext context, int length) { ProtoReader.Init(this, source, model, context, length); } private static void Init(ProtoReader reader, Stream source, TypeModel model, SerializationContext context, int length) { bool flag = source == null; if (flag) { throw new ArgumentNullException("source"); } bool flag2 = !source.CanRead; if (flag2) { throw new ArgumentException("Cannot read from stream", "source"); } reader.source = source; reader.ioBuffer = BufferPool.GetBuffer(); reader.model = model; bool flag3 = length >= 0; reader.isFixedLength = flag3; reader.dataRemaining = (flag3 ? length : 0); bool flag4 = context == null; if (flag4) { context = SerializationContext.Default; } else { context.Freeze(); } reader.context = context; reader.position = (reader.available = (reader.depth = (reader.fieldNumber = (reader.ioIndex = 0)))); reader.blockEnd = int.MaxValue; reader.internStrings = true; reader.wireType = WireType.None; reader.trapCount = 1u; bool flag5 = reader.netCache == null; if (flag5) { reader.netCache = new NetObjectCache(); } } public void Dispose() { this.source = null; this.model = null; BufferPool.ReleaseBufferToPool(ref this.ioBuffer); bool flag = this.stringInterner != null; if (flag) { this.stringInterner.Clear(); } bool flag2 = this.netCache != null; if (flag2) { this.netCache.Clear(); } } internal int TryReadUInt32VariantWithoutMoving(bool trimNegative, out uint value) { bool flag = this.available < 10; if (flag) { this.Ensure(10, false); } bool flag2 = this.available == 0; int result; if (flag2) { value = 0u; result = 0; } else { int num = this.ioIndex; value = (uint)this.ioBuffer[num++]; bool flag3 = (value & 128u) == 0u; if (flag3) { result = 1; } else { value &= 127u; bool flag4 = this.available == 1; if (flag4) { throw ProtoReader.EoF(this); } uint num2 = (uint)this.ioBuffer[num++]; value |= (num2 & 127u) << 7; bool flag5 = (num2 & 128u) == 0u; if (flag5) { result = 2; } else { bool flag6 = this.available == 2; if (flag6) { throw ProtoReader.EoF(this); } num2 = (uint)this.ioBuffer[num++]; value |= (num2 & 127u) << 14; bool flag7 = (num2 & 128u) == 0u; if (flag7) { result = 3; } else { bool flag8 = this.available == 3; if (flag8) { throw ProtoReader.EoF(this); } num2 = (uint)this.ioBuffer[num++]; value |= (num2 & 127u) << 21; bool flag9 = (num2 & 128u) == 0u; if (flag9) { result = 4; } else { bool flag10 = this.available == 4; if (flag10) { throw ProtoReader.EoF(this); } num2 = (uint)this.ioBuffer[num]; value |= num2 << 28; bool flag11 = (num2 & 240u) == 0u; if (flag11) { result = 5; } else { bool flag12 = trimNegative && (num2 & 240u) == 240u && this.available >= 10 && this.ioBuffer[++num] == byte.MaxValue && this.ioBuffer[++num] == byte.MaxValue && this.ioBuffer[++num] == byte.MaxValue && this.ioBuffer[++num] == byte.MaxValue && this.ioBuffer[num + 1] == 1; if (!flag12) { throw ProtoReader.AddErrorData(new OverflowException(), this); } result = 10; } } } } } } return result; } private uint ReadUInt32Variant(bool trimNegative) { uint result; int num = this.TryReadUInt32VariantWithoutMoving(trimNegative, out result); bool flag = num > 0; if (flag) { this.ioIndex += num; this.available -= num; this.position += num; return result; } throw ProtoReader.EoF(this); } private bool TryReadUInt32Variant(out uint value) { int num = this.TryReadUInt32VariantWithoutMoving(false, out value); bool flag = num > 0; bool result; if (flag) { this.ioIndex += num; this.available -= num; this.position += num; result = true; } else { result = false; } return result; } public uint ReadUInt32() { WireType wireType = this.wireType; uint result; if (wireType != WireType.Variant) { if (wireType != WireType.Fixed64) { if (wireType != WireType.Fixed32) { throw this.CreateWireTypeException(); } bool flag = this.available < 4; if (flag) { this.Ensure(4, true); } this.position += 4; this.available -= 4; byte[] array = this.ioBuffer; int num = this.ioIndex; this.ioIndex = num + 1; uint num2 = array[num]; byte[] array2 = this.ioBuffer; num = this.ioIndex; this.ioIndex = num + 1; uint num3 = (uint)(num2 | array2[num] << 8); byte[] array3 = this.ioBuffer; num = this.ioIndex; this.ioIndex = num + 1; uint num4 = (uint)(num3 | array3[num] << 16); byte[] array4 = this.ioBuffer; num = this.ioIndex; this.ioIndex = num + 1; result = (uint)(num4 | array4[num] << 24); } else { ulong num5 = this.ReadUInt64(); result = checked((uint)num5); } } else { result = this.ReadUInt32Variant(false); } return result; } internal void Ensure(int count, bool strict) { Helpers.DebugAssert(this.available <= count, "Asking for data without checking first"); bool flag = count > this.ioBuffer.Length; if (flag) { BufferPool.ResizeAndFlushLeft(ref this.ioBuffer, count, this.ioIndex, this.available); this.ioIndex = 0; } else { bool flag2 = this.ioIndex + count >= this.ioBuffer.Length; if (flag2) { Helpers.BlockCopy(this.ioBuffer, this.ioIndex, this.ioBuffer, 0, this.available); this.ioIndex = 0; } } count -= this.available; int num = this.ioIndex + this.available; int num2 = this.ioBuffer.Length - num; bool flag3 = this.isFixedLength; if (flag3) { bool flag4 = this.dataRemaining < num2; if (flag4) { num2 = this.dataRemaining; } } int num3; while (count > 0 && num2 > 0 && (num3 = this.source.Read(this.ioBuffer, num, num2)) > 0) { this.available += num3; count -= num3; num2 -= num3; num += num3; bool flag5 = this.isFixedLength; if (flag5) { this.dataRemaining -= num3; } } bool flag6 = strict && count > 0; if (flag6) { throw ProtoReader.EoF(this); } } public short ReadInt16() { return checked((short)this.ReadInt32()); } public ushort ReadUInt16() { return checked((ushort)this.ReadUInt32()); } public byte ReadByte() { return checked((byte)this.ReadUInt32()); } public sbyte ReadSByte() { return checked((sbyte)this.ReadInt32()); } public int ReadInt32() { WireType wireType = this.wireType; if (wireType <= WireType.Fixed64) { if (wireType == WireType.Variant) { return (int)this.ReadUInt32Variant(true); } if (wireType == WireType.Fixed64) { long num = this.ReadInt64(); return checked((int)num); } } else { if (wireType == WireType.Fixed32) { bool flag = this.available < 4; if (flag) { this.Ensure(4, true); } this.position += 4; this.available -= 4; byte[] array = this.ioBuffer; int num2 = this.ioIndex; this.ioIndex = num2 + 1; int num3 = array[num2]; byte[] array2 = this.ioBuffer; num2 = this.ioIndex; this.ioIndex = num2 + 1; int num4 = num3 | array2[num2] << 8; byte[] array3 = this.ioBuffer; num2 = this.ioIndex; this.ioIndex = num2 + 1; int num5 = num4 | array3[num2] << 16; byte[] array4 = this.ioBuffer; num2 = this.ioIndex; this.ioIndex = num2 + 1; return num5 | array4[num2] << 24; } if (wireType == WireType.SignedVariant) { return ProtoReader.Zag(this.ReadUInt32Variant(true)); } } throw this.CreateWireTypeException(); } private static int Zag(uint ziggedValue) { return (int)(-(ziggedValue & 1u) ^ (uint)((int)ziggedValue >> 1 & int.MaxValue)); } private static long Zag(ulong ziggedValue) { //! //return (long)(-(long)(ziggedValue & 1UL) ^ (ziggedValue >> 1 & 9223372036854775807UL)); long rightPart = (long)( ziggedValue >> 1 & long.MaxValue ); long leftPart = -(long)(ziggedValue & 1UL); return leftPart ^ rightPart; } public long ReadInt64() { WireType wireType = this.wireType; if (wireType <= WireType.Fixed64) { if (wireType == WireType.Variant) { return (long)this.ReadUInt64Variant(); } if (wireType == WireType.Fixed64) { bool flag = this.available < 8; if (flag) { this.Ensure(8, true); } this.position += 8; this.available -= 8; byte[] array = this.ioBuffer; int num = this.ioIndex; this.ioIndex = num + 1; long num2 = (long)array[num]; byte[] array2 = this.ioBuffer; num = this.ioIndex; this.ioIndex = num + 1; long num3 = num2 | (long)((long)array2[num] << 8); byte[] array3 = this.ioBuffer; num = this.ioIndex; this.ioIndex = num + 1; long num4 = num3 | (long)((long)array3[num] << 16); byte[] array4 = this.ioBuffer; num = this.ioIndex; this.ioIndex = num + 1; long num5 = num4 | (long)((long)array4[num] << 24); byte[] array5 = this.ioBuffer; num = this.ioIndex; this.ioIndex = num + 1; long num6 = num5 | (long)((long)array5[num] << 32); byte[] array6 = this.ioBuffer; num = this.ioIndex; this.ioIndex = num + 1; long num7 = num6 | (long)((long)array6[num] << 40); byte[] array7 = this.ioBuffer; num = this.ioIndex; this.ioIndex = num + 1; long num8 = num7 | (long)((long)array7[num] << 48); byte[] array8 = this.ioBuffer; num = this.ioIndex; this.ioIndex = num + 1; return num8 | (long)((long)array8[num] << 56); } } else { if (wireType == WireType.Fixed32) { return (long)this.ReadInt32(); } if (wireType == WireType.SignedVariant) { return ProtoReader.Zag(this.ReadUInt64Variant()); } } throw this.CreateWireTypeException(); } private int TryReadUInt64VariantWithoutMoving(out ulong value) { bool flag = this.available < 10; if (flag) { this.Ensure(10, false); } bool flag2 = this.available == 0; int result; if (flag2) { value = 0UL; result = 0; } else { int num = this.ioIndex; value = (ulong)this.ioBuffer[num++]; bool flag3 = (value & 128UL) == 0UL; if (flag3) { result = 1; } else { value &= 127UL; bool flag4 = this.available == 1; if (flag4) { throw ProtoReader.EoF(this); } ulong num2 = (ulong)this.ioBuffer[num++]; value |= (num2 & 127UL) << 7; bool flag5 = (num2 & 128UL) == 0UL; if (flag5) { result = 2; } else { bool flag6 = this.available == 2; if (flag6) { throw ProtoReader.EoF(this); } num2 = (ulong)this.ioBuffer[num++]; value |= (num2 & 127UL) << 14; bool flag7 = (num2 & 128UL) == 0UL; if (flag7) { result = 3; } else { bool flag8 = this.available == 3; if (flag8) { throw ProtoReader.EoF(this); } num2 = (ulong)this.ioBuffer[num++]; value |= (num2 & 127UL) << 21; bool flag9 = (num2 & 128UL) == 0UL; if (flag9) { result = 4; } else { bool flag10 = this.available == 4; if (flag10) { throw ProtoReader.EoF(this); } num2 = (ulong)this.ioBuffer[num++]; value |= (num2 & 127UL) << 28; bool flag11 = (num2 & 128UL) == 0UL; if (flag11) { result = 5; } else { bool flag12 = this.available == 5; if (flag12) { throw ProtoReader.EoF(this); } num2 = (ulong)this.ioBuffer[num++]; value |= (num2 & 127UL) << 35; bool flag13 = (num2 & 128UL) == 0UL; if (flag13) { result = 6; } else { bool flag14 = this.available == 6; if (flag14) { throw ProtoReader.EoF(this); } num2 = (ulong)this.ioBuffer[num++]; value |= (num2 & 127UL) << 42; bool flag15 = (num2 & 128UL) == 0UL; if (flag15) { result = 7; } else { bool flag16 = this.available == 7; if (flag16) { throw ProtoReader.EoF(this); } num2 = (ulong)this.ioBuffer[num++]; value |= (num2 & 127UL) << 49; bool flag17 = (num2 & 128UL) == 0UL; if (flag17) { result = 8; } else { bool flag18 = this.available == 8; if (flag18) { throw ProtoReader.EoF(this); } num2 = (ulong)this.ioBuffer[num++]; value |= (num2 & 127UL) << 56; bool flag19 = (num2 & 128UL) == 0UL; if (flag19) { result = 9; } else { bool flag20 = this.available == 9; if (flag20) { throw ProtoReader.EoF(this); } num2 = (ulong)this.ioBuffer[num]; value |= num2 << 63; bool flag21 = (num2 & 18446744073709551614UL) > 0UL; if (flag21) { throw ProtoReader.AddErrorData(new OverflowException(), this); } result = 10; } } } } } } } } } } return result; } private ulong ReadUInt64Variant() { ulong result; int num = this.TryReadUInt64VariantWithoutMoving(out result); bool flag = num > 0; if (flag) { this.ioIndex += num; this.available -= num; this.position += num; return result; } throw ProtoReader.EoF(this); } private string Intern(string value) { bool flag = value == null; string result; if (flag) { result = null; } else { bool flag2 = value.Length == 0; if (flag2) { result = ""; } else { bool flag3 = this.stringInterner == null; if (flag3) { this.stringInterner = new Dictionary(); this.stringInterner.Add(value, value); } else { string text; bool flag4 = this.stringInterner.TryGetValue(value, out text); if (flag4) { value = text; } else { this.stringInterner.Add(value, value); } } result = value; } } return result; } public string ReadString() { bool flag = this.wireType == WireType.String; if (flag) { int num = (int)this.ReadUInt32Variant(false); bool flag2 = num == 0; string result; if (flag2) { result = ""; } else { bool flag3 = this.available < num; if (flag3) { this.Ensure(num, true); } string text = ProtoReader.encoding.GetString(this.ioBuffer, this.ioIndex, num); bool flag4 = this.internStrings; if (flag4) { text = this.Intern(text); } this.available -= num; this.position += num; this.ioIndex += num; result = text; } return result; } throw this.CreateWireTypeException(); } public void ThrowEnumException(Type type, int value) { string str = (type == null) ? "" : type.FullName; throw ProtoReader.AddErrorData(new ProtoException("No " + str + " enum is mapped to the wire-value " + value.ToString()), this); } private Exception CreateWireTypeException() { return this.CreateException("Invalid wire-type; this usually means you have over-written a file without truncating or setting the length; see http://stackoverflow.com/q/2152978/23354"); } private Exception CreateException(string message) { return ProtoReader.AddErrorData(new ProtoException(message), this); } public unsafe double ReadDouble() { WireType wireType = this.wireType; double result; if (wireType != WireType.Fixed64) { if (wireType != WireType.Fixed32) { throw this.CreateWireTypeException(); } result = (double)this.ReadSingle(); } else { long num = this.ReadInt64(); result = *(double*)(&num); } return result; } public static object ReadObject(object value, int key, ProtoReader reader) { return ProtoReader.ReadTypedObject(value, key, reader, null); } internal static object ReadTypedObject(object value, int key, ProtoReader reader, Type type) { bool flag = reader.model == null; if (flag) { throw ProtoReader.AddErrorData(new InvalidOperationException("Cannot deserialize sub-objects unless a model is provided"), reader); } SubItemToken token = ProtoReader.StartSubItem(reader); bool flag2 = key >= 0; if (flag2) { value = reader.model.Deserialize(key, value, reader); } else { bool flag3 = type != null && reader.model.TryDeserializeAuxiliaryType(reader, DataFormat.Default, 1, type, ref value, true, false, true, false); if (!flag3) { TypeModel.ThrowUnexpectedType(type); } } ProtoReader.EndSubItem(token, reader); return value; } public static void EndSubItem(SubItemToken token, ProtoReader reader) { bool flag = reader == null; if (flag) { throw new ArgumentNullException("reader"); } int value = token.value; WireType wireType = reader.wireType; if (wireType != WireType.EndGroup) { bool flag2 = value < reader.position; if (flag2) { throw reader.CreateException("Sub-message not read entirely"); } bool flag3 = reader.blockEnd != reader.position && reader.blockEnd != int.MaxValue; if (flag3) { throw reader.CreateException("Sub-message not read correctly"); } reader.blockEnd = value; reader.depth--; } else { bool flag4 = value >= 0; if (flag4) { throw ProtoReader.AddErrorData(new ArgumentException("token"), reader); } bool flag5 = -value != reader.fieldNumber; if (flag5) { throw reader.CreateException("Wrong group was ended"); } reader.wireType = WireType.None; reader.depth--; } } public static SubItemToken StartSubItem(ProtoReader reader) { bool flag = reader == null; if (flag) { throw new ArgumentNullException("reader"); } WireType wireType = reader.wireType; SubItemToken result; if (wireType != WireType.String) { if (wireType != WireType.StartGroup) { throw reader.CreateWireTypeException(); } reader.wireType = WireType.None; reader.depth++; result = new SubItemToken(-reader.fieldNumber); } else { int num = (int)reader.ReadUInt32Variant(false); bool flag2 = num < 0; if (flag2) { throw ProtoReader.AddErrorData(new InvalidOperationException(), reader); } int value = reader.blockEnd; reader.blockEnd = reader.position + num; reader.depth++; result = new SubItemToken(value); } return result; } public int ReadFieldHeader() { bool flag = this.blockEnd <= this.position || this.wireType == WireType.EndGroup; int result; if (flag) { result = 0; } else { uint num; bool flag2 = this.TryReadUInt32Variant(out num); if (flag2) { this.wireType = (WireType)(num & 7u); this.fieldNumber = (int)(num >> 3); bool flag3 = this.fieldNumber < 1; if (flag3) { throw new ProtoException("Invalid field in source data: " + this.fieldNumber.ToString()); } } else { this.wireType = WireType.None; this.fieldNumber = 0; } bool flag4 = this.wireType == WireType.EndGroup; if (flag4) { bool flag5 = this.depth > 0; if (!flag5) { throw new ProtoException("Unexpected end-group in source data; this usually means the source data is corrupt"); } result = 0; } else { result = this.fieldNumber; } } return result; } public bool TryReadFieldHeader(int field) { bool flag = this.blockEnd <= this.position || this.wireType == WireType.EndGroup; bool result; if (flag) { result = false; } else { uint num2; int num = this.TryReadUInt32VariantWithoutMoving(false, out num2); WireType wireType = WireType.None; bool flag2 = num > 0 && (int)num2 >> 3 == field && (wireType = (WireType)(num2 & 7u)) != WireType.EndGroup; if (flag2) { this.wireType = wireType; this.fieldNumber = field; this.position += num; this.ioIndex += num; this.available -= num; result = true; } else { result = false; } } return result; } public void Hint(WireType wireType) { bool flag = this.wireType == wireType; if (!flag) { bool flag2 = (wireType & (WireType)7) == this.wireType; if (flag2) { this.wireType = wireType; } } } public void Assert(WireType wireType) { bool flag = this.wireType == wireType; if (!flag) { bool flag2 = (wireType & (WireType)7) == this.wireType; if (!flag2) { throw this.CreateWireTypeException(); } this.wireType = wireType; } } public void SkipField() { switch (this.wireType) { case WireType.Variant: case WireType.SignedVariant: this.ReadUInt64Variant(); return; case WireType.Fixed64: { bool flag = this.available < 8; if (flag) { this.Ensure(8, true); } this.available -= 8; this.ioIndex += 8; this.position += 8; return; } case WireType.String: { int num = (int)this.ReadUInt32Variant(false); bool flag2 = num <= this.available; if (flag2) { this.available -= num; this.ioIndex += num; this.position += num; return; } this.position += num; num -= this.available; this.ioIndex = (this.available = 0); bool flag3 = this.isFixedLength; if (flag3) { bool flag4 = num > this.dataRemaining; if (flag4) { throw ProtoReader.EoF(this); } this.dataRemaining -= num; } ProtoReader.Seek(this.source, num, this.ioBuffer); return; } case WireType.StartGroup: { int num2 = this.fieldNumber; this.depth++; while (this.ReadFieldHeader() > 0) { this.SkipField(); } this.depth--; bool flag5 = this.wireType == WireType.EndGroup && this.fieldNumber == num2; if (flag5) { this.wireType = WireType.None; return; } throw this.CreateWireTypeException(); } case WireType.Fixed32: { bool flag6 = this.available < 4; if (flag6) { this.Ensure(4, true); } this.available -= 4; this.ioIndex += 4; this.position += 4; return; } } throw this.CreateWireTypeException(); } public ulong ReadUInt64() { WireType wireType = this.wireType; ulong result; if (wireType != WireType.Variant) { if (wireType != WireType.Fixed64) { if (wireType != WireType.Fixed32) { throw this.CreateWireTypeException(); } result = (ulong)this.ReadUInt32(); } else { bool flag = this.available < 8; if (flag) { this.Ensure(8, true); } this.position += 8; this.available -= 8; byte[] array = this.ioBuffer; int num = this.ioIndex; this.ioIndex = num + 1; ulong num2 = array[num]; byte[] array2 = this.ioBuffer; num = this.ioIndex; this.ioIndex = num + 1; ulong num3 = num2 | (ulong) ( array2[num] << 8); byte[] array3 = this.ioBuffer; num = this.ioIndex; this.ioIndex = num + 1; ulong num4 = num3 | (ulong) (array3[num] << 16); byte[] array4 = this.ioBuffer; num = this.ioIndex; this.ioIndex = num + 1; ulong num5 = num4 | (ulong) ( array4[num] << 24); byte[] array5 = this.ioBuffer; num = this.ioIndex; this.ioIndex = num + 1; ulong num6 = num5 | (ulong)(array5[num] << 32); byte[] array6 = this.ioBuffer; num = this.ioIndex; this.ioIndex = num + 1; ulong num7 = num6 | (ulong)( array6[num] << 40); byte[] array7 = this.ioBuffer; num = this.ioIndex; this.ioIndex = num + 1; ulong num8 = num7 | (ulong)(array7[num] << 48); byte[] array8 = this.ioBuffer; num = this.ioIndex; this.ioIndex = num + 1; result = (num8 | (ulong) ( array8[num] << 56)); } } else { result = this.ReadUInt64Variant(); } return result; } public unsafe float ReadSingle() { WireType wireType = this.wireType; float result; if (wireType != WireType.Fixed64) { if (wireType != WireType.Fixed32) { throw this.CreateWireTypeException(); } int num = this.ReadInt32(); result = *(float*)(&num); } else { double num2 = this.ReadDouble(); float num3 = (float)num2; bool flag = Helpers.IsInfinity(num3) && !Helpers.IsInfinity(num2); if (flag) { throw ProtoReader.AddErrorData(new OverflowException(), this); } result = num3; } return result; } public bool ReadBoolean() { uint num = this.ReadUInt32(); bool result; if (num != 0u) { if (num != 1u) { throw this.CreateException("Unexpected boolean value"); } result = true; } else { result = false; } return result; } public static byte[] AppendBytes(byte[] value, ProtoReader reader) { bool flag = reader == null; if (flag) { throw new ArgumentNullException("reader"); } WireType wireType = reader.wireType; if (wireType != WireType.String) { throw reader.CreateWireTypeException(); } int i = (int)reader.ReadUInt32Variant(false); reader.wireType = WireType.None; bool flag2 = i == 0; byte[] result; if (flag2) { result = ((value == null) ? ProtoReader.EmptyBlob : value); } else { bool flag3 = value == null || value.Length == 0; int num; if (flag3) { num = 0; value = new byte[i]; } else { num = value.Length; byte[] array = new byte[value.Length + i]; Helpers.BlockCopy(value, 0, array, 0, value.Length); value = array; } reader.position += i; while (i > reader.available) { bool flag4 = reader.available > 0; if (flag4) { Helpers.BlockCopy(reader.ioBuffer, reader.ioIndex, value, num, reader.available); i -= reader.available; num += reader.available; reader.ioIndex = (reader.available = 0); } int num2 = (i > reader.ioBuffer.Length) ? reader.ioBuffer.Length : i; bool flag5 = num2 > 0; if (flag5) { reader.Ensure(num2, true); } } bool flag6 = i > 0; if (flag6) { Helpers.BlockCopy(reader.ioBuffer, reader.ioIndex, value, num, i); reader.ioIndex += i; reader.available -= i; } result = value; } return result; } private static int ReadByteOrThrow(Stream source) { int num = source.ReadByte(); bool flag = num < 0; if (flag) { throw ProtoReader.EoF(null); } return num; } public static int ReadLengthPrefix(Stream source, bool expectHeader, PrefixStyle style, out int fieldNumber) { int num; return ProtoReader.ReadLengthPrefix(source, expectHeader, style, out fieldNumber, out num); } public static int DirectReadLittleEndianInt32(Stream source) { return ProtoReader.ReadByteOrThrow(source) | ProtoReader.ReadByteOrThrow(source) << 8 | ProtoReader.ReadByteOrThrow(source) << 16 | ProtoReader.ReadByteOrThrow(source) << 24; } public static int DirectReadBigEndianInt32(Stream source) { return ProtoReader.ReadByteOrThrow(source) << 24 | ProtoReader.ReadByteOrThrow(source) << 16 | ProtoReader.ReadByteOrThrow(source) << 8 | ProtoReader.ReadByteOrThrow(source); } public static int DirectReadVarintInt32(Stream source) { uint result; int num = ProtoReader.TryReadUInt32Variant(source, out result); bool flag = num <= 0; if (flag) { throw ProtoReader.EoF(null); } return (int)result; } public static void DirectReadBytes(Stream source, byte[] buffer, int offset, int count) { bool flag = source == null; if (flag) { throw new ArgumentNullException("source"); } int num; while (count > 0 && (num = source.Read(buffer, offset, count)) > 0) { count -= num; offset += num; } bool flag2 = count > 0; if (flag2) { throw ProtoReader.EoF(null); } } public static byte[] DirectReadBytes(Stream source, int count) { byte[] array = new byte[count]; ProtoReader.DirectReadBytes(source, array, 0, count); return array; } public static string DirectReadString(Stream source, int length) { byte[] array = new byte[length]; ProtoReader.DirectReadBytes(source, array, 0, length); return Encoding.UTF8.GetString(array, 0, length); } public static int ReadLengthPrefix(Stream source, bool expectHeader, PrefixStyle style, out int fieldNumber, out int bytesRead) { fieldNumber = 0; int result; switch (style) { case PrefixStyle.None: bytesRead = 0; result = int.MaxValue; break; case PrefixStyle.Base128: bytesRead = 0; if (expectHeader) { uint num2; int num = ProtoReader.TryReadUInt32Variant(source, out num2); bytesRead += num; bool flag = num > 0; if (flag) { bool flag2 = (num2 & 7u) != 2u; if (flag2) { throw new InvalidOperationException(); } fieldNumber = (int)(num2 >> 3); num = ProtoReader.TryReadUInt32Variant(source, out num2); bytesRead += num; bool flag3 = bytesRead == 0; if (flag3) { throw ProtoReader.EoF(null); } result = (int)num2; } else { bytesRead = 0; result = -1; } } else { uint num2; int num = ProtoReader.TryReadUInt32Variant(source, out num2); bytesRead += num; result = (int)((bytesRead < 0) ? uint.MaxValue : num2); } break; case PrefixStyle.Fixed32: { int num3 = source.ReadByte(); bool flag4 = num3 < 0; if (flag4) { bytesRead = 0; result = -1; } else { bytesRead = 4; result = (num3 | ProtoReader.ReadByteOrThrow(source) << 8 | ProtoReader.ReadByteOrThrow(source) << 16 | ProtoReader.ReadByteOrThrow(source) << 24); } break; } case PrefixStyle.Fixed32BigEndian: { int num4 = source.ReadByte(); bool flag5 = num4 < 0; if (flag5) { bytesRead = 0; result = -1; } else { bytesRead = 4; result = (num4 << 24 | ProtoReader.ReadByteOrThrow(source) << 16 | ProtoReader.ReadByteOrThrow(source) << 8 | ProtoReader.ReadByteOrThrow(source)); } break; } default: throw new ArgumentOutOfRangeException("style"); } return result; } private static int TryReadUInt32Variant(Stream source, out uint value) { value = 0u; int num = source.ReadByte(); bool flag = num < 0; int result; if (flag) { result = 0; } else { value = (uint)num; bool flag2 = (value & 128u) == 0u; if (flag2) { result = 1; } else { value &= 127u; num = source.ReadByte(); bool flag3 = num < 0; if (flag3) { throw ProtoReader.EoF(null); } value |= (uint)((uint)(num & 127) << 7); bool flag4 = (num & 128) == 0; if (flag4) { result = 2; } else { num = source.ReadByte(); bool flag5 = num < 0; if (flag5) { throw ProtoReader.EoF(null); } value |= (uint)((uint)(num & 127) << 14); bool flag6 = (num & 128) == 0; if (flag6) { result = 3; } else { num = source.ReadByte(); bool flag7 = num < 0; if (flag7) { throw ProtoReader.EoF(null); } value |= (uint)((uint)(num & 127) << 21); bool flag8 = (num & 128) == 0; if (flag8) { result = 4; } else { num = source.ReadByte(); bool flag9 = num < 0; if (flag9) { throw ProtoReader.EoF(null); } value |= (uint)((uint)num << 28); bool flag10 = (num & 240) == 0; if (!flag10) { throw new OverflowException(); } result = 5; } } } } } return result; } internal static void Seek(Stream source, int count, byte[] buffer) { bool canSeek = source.CanSeek; if (canSeek) { source.Seek((long)count, SeekOrigin.Current); count = 0; } else { bool flag = buffer != null; if (flag) { int num; while (count > buffer.Length && (num = source.Read(buffer, 0, buffer.Length)) > 0) { count -= num; } while (count > 0 && (num = source.Read(buffer, 0, count)) > 0) { count -= num; } } else { buffer = BufferPool.GetBuffer(); try { int num2; while (count > buffer.Length && (num2 = source.Read(buffer, 0, buffer.Length)) > 0) { count -= num2; } while (count > 0 && (num2 = source.Read(buffer, 0, count)) > 0) { count -= num2; } } finally { BufferPool.ReleaseBufferToPool(ref buffer); } } } bool flag2 = count > 0; if (flag2) { throw ProtoReader.EoF(null); } } internal static Exception AddErrorData(Exception exception, ProtoReader source) { bool flag = exception != null && source != null && !exception.Data.Contains("protoSource"); if (flag) { exception.Data.Add("protoSource", string.Format("tag={0}; wire-type={1}; offset={2}; depth={3}", new object[] { source.fieldNumber, source.wireType, source.position, source.depth })); } return exception; } private static Exception EoF(ProtoReader source) { return ProtoReader.AddErrorData(new EndOfStreamException(), source); } public void AppendExtensionData(IExtensible instance) { bool flag = instance == null; if (flag) { throw new ArgumentNullException("instance"); } IExtension extensionObject = instance.GetExtensionObject(true); bool commit = false; Stream stream = extensionObject.BeginAppend(); try { using (ProtoWriter protoWriter = new ProtoWriter(stream, this.model, null)) { this.AppendExtensionField(protoWriter); protoWriter.Close(); } commit = true; } finally { extensionObject.EndAppend(stream, commit); } } private void AppendExtensionField(ProtoWriter writer) { ProtoWriter.WriteFieldHeader(this.fieldNumber, this.wireType, writer); switch (this.wireType) { case WireType.Variant: case WireType.Fixed64: case WireType.SignedVariant: ProtoWriter.WriteInt64(this.ReadInt64(), writer); return; case WireType.String: ProtoWriter.WriteBytes(ProtoReader.AppendBytes(null, this), writer); return; case WireType.StartGroup: { SubItemToken token = ProtoReader.StartSubItem(this); SubItemToken token2 = ProtoWriter.StartSubItem(null, writer); while (this.ReadFieldHeader() > 0) { this.AppendExtensionField(writer); } ProtoReader.EndSubItem(token, this); ProtoWriter.EndSubItem(token2, writer); return; } case WireType.Fixed32: ProtoWriter.WriteInt32(this.ReadInt32(), writer); return; } throw this.CreateWireTypeException(); } public static bool HasSubValue(WireType wireType, ProtoReader source) { bool flag = source == null; if (flag) { throw new ArgumentNullException("source"); } bool flag2 = source.blockEnd <= source.position || wireType == WireType.EndGroup; bool result; if (flag2) { result = false; } else { source.wireType = wireType; result = true; } return result; } internal int GetTypeKey(ref Type type) { return this.model.GetKey(ref type); } internal Type DeserializeType(string value) { return TypeModel.DeserializeType(this.model, value); } internal void SetRootObject(object value) { this.netCache.SetKeyedObject(0, value); this.trapCount -= 1u; } public static void NoteObject(object value, ProtoReader reader) { bool flag = reader == null; if (flag) { throw new ArgumentNullException("reader"); } bool flag2 = reader.trapCount > 0u; if (flag2) { reader.netCache.RegisterTrappedObject(value); reader.trapCount -= 1u; } } public Type ReadType() { return TypeModel.DeserializeType(this.model, this.ReadString()); } internal void TrapNextObject(int newObjectKey) { this.trapCount += 1u; this.netCache.SetKeyedObject(newObjectKey, null); } internal void CheckFullyConsumed() { bool flag = this.isFixedLength; if (flag) { bool flag2 = this.dataRemaining != 0; if (flag2) { throw new ProtoException("Incorrect number of bytes consumed"); } } else { bool flag3 = this.available != 0; if (flag3) { throw new ProtoException("Unconsumed data left in the buffer; this suggests corrupt input"); } } } public static object Merge(ProtoReader parent, object from, object to) { bool flag = parent == null; if (flag) { throw new ArgumentNullException("parent"); } TypeModel typeModel = parent.Model; SerializationContext serializationContext = parent.Context; bool flag2 = typeModel == null; if (flag2) { throw new InvalidOperationException("Types cannot be merged unless a type-model has been specified"); } object result; using (MemoryStream memoryStream = new MemoryStream()) { typeModel.Serialize(memoryStream, from, serializationContext); memoryStream.Position = 0L; result = typeModel.Deserialize(memoryStream, to, null); } return result; } internal static ProtoReader Create(Stream source, TypeModel model, SerializationContext context, int len) { ProtoReader recycled = ProtoReader.GetRecycled(); bool flag = recycled == null; ProtoReader result; if (flag) { result = new ProtoReader(source, model, context, len); } else { ProtoReader.Init(recycled, source, model, context, len); result = recycled; } return result; } private static ProtoReader GetRecycled() { ProtoReader result = ProtoReader.lastReader; ProtoReader.lastReader = null; return result; } internal static void Recycle(ProtoReader reader) { bool flag = reader != null; if (flag) { reader.Dispose(); ProtoReader.lastReader = reader; } } } }