/// <summary>
 ///     Increases <c>index</c> by 8
 /// </summary>
 public void IncreaseIndexBy8()
 {
     LoadIndexByRef();      // stack: [ref index]
     LoadIndex();           // stack: [ref index, index]
     Il.Ldc_I4(8);          // stack: [ref index, index, 8]
     Il.Add();              // stack: [ref index, index + 8]
     Il.Stind(typeof(int)); // index = index + 8
 }
        public void SkipValue()
        {
            LoadIndexByRef(); // stack: [ref index]
            LoadIndex();      // stack: [ref index, index]

            // todo: сделать switch
            Il.Ldloc(TypeCode);                         // stack: [ref index, index, TypeCode]
            Il.Ldc_I4((int)GroBufTypeCode.DateTimeOld); // stack: [ref index, index, TypeCode, GroBufTypeCode.DateTimeOld]
            var notDateTimeLabel = Il.DefineLabel("notDateTime");

            Il.Bne_Un(notDateTimeLabel); // if(TypeCode != GroBufTypeCode.DateTimeOld) goto notDateTime; stack: [ref index, index]
            Il.Ldc_I4(8);                // stack: [ref index, index, 8]
            AssertLength();
            GoToCurrentLocation();       // stack: [ref index, index, &data[index]]
            Il.Ldc_I4(4);
            Il.Add();
            Il.Ldind(typeof(int)); // stack: [ref index, index, (int)(&data[index])]
            Il.Ldc_I4(31);         // stack: [ref index, index, (int)&data[index], 31]
            Il.Shr(true);          // stack: [ref index, index, (int)&data[index] >> 31]
            Il.Ldc_I4(8);          // stack: [ref index, index, (int)&data[index] >> 31, 8]
            Il.Add();              // stack: [ref index, index, (int)&data[index] >> 31 + 8]
            var increaseLabel = Il.DefineLabel("increase");

            Il.Br(increaseLabel);

            Il.MarkLabel(notDateTimeLabel);
            LoadField(Context.Lengths);

            Il.Ldloc(TypeCode);       // stack: [ref index, index, lengths, typeCode]
            Il.Ldelem(typeof(int));   // stack: [ref index, index, lengths[typeCode]]
            Il.Dup();                 // stack: [ref index, index, lengths[typeCode], lengths[typeCode]]
            Il.Ldc_I4(-1);            // stack: [ref index, index, lengths[typeCode], lengths[typeCode], -1]
            Il.Bne_Un(increaseLabel); // if(lengths[typeCode] != -1) goto increase;

            Il.Ldc_I4(4);
            AssertLength();
            Il.Pop();               // stack: [ref index, index]
            Il.Dup();               // stack: [ref index, index, index]
            LoadData();             // stack: [ref index, index, index, pinnedData]
            Il.Add();               // stack: [ref index, index, index + pinnedData]
            Il.Ldind(typeof(uint)); // stack: [ref index, index, *(uint*)(pinnedData + index)]
            Il.Ldc_I4(4);           // stack: [ref index, index, *(uint*)(pinnedData + index), 4]
            Il.Add();               // stack: [ref index, *(uint*)(pinnedData + index) + 4]

            Il.MarkLabel(increaseLabel);
            Il.Dup();              // stack: [ref index, length, length]
            AssertLength();        // stack: [ref index, length]
            Il.Add();              // stack: [ref index, index + length]
            Il.Stind(typeof(int)); // index = index + length
        }
        /// <summary>
        ///     Asserts that the specified number of bytes can be read from <c>data</c> starting at <c>index</c>
        ///     <para></para>
        ///     The number of bytes must be pushed onto the evaluation stack
        /// </summary>
        public void AssertLength()
        {
            LoadIndex();      // stack: [length, index]
            Il.Add();         // stack: [length + index]
            LoadDataLength(); // stack: [length + index, dataLength]
            var bigEnoughLabel = Il.DefineLabel("bigEnough");

            Il.Ble(bigEnoughLabel, true);
            Il.Ldstr("Unexpected end of data");
            var constructor = typeof(DataCorruptedException).GetConstructor(new[] { typeof(string) });

            if (constructor == null)
            {
                throw new MissingConstructorException(typeof(DataCorruptedException), typeof(string));
            }
            Il.Newobj(constructor);
            Il.Throw();
            Il.MarkLabel(bigEnoughLabel);
        }
        /// <summary>
        ///     Asserts that the specified number of bytes can be written to <c>result</c> starting at <c>index</c>
        ///     <para></para>
        ///     The number of bytes must be pushed onto the evaluation stack
        /// </summary>
        public void AssertLength()
        {
            LoadIndex();        // stack: [length, index]
            Il.Add();           // stack: [length + index]
            LoadResultLength(); // stack: [length + index, resultLength]
            var bigEnoughLabel = Il.DefineLabel("bigEnough");

            Il.Ble(bigEnoughLabel, true);
            Il.Ldstr("Seems like the object being serialized has been changed during serialization");
            var constructor = typeof(InvalidOperationException).GetConstructor(new[] { typeof(string) });

            if (constructor == null)
            {
                throw new MissingConstructorException(typeof(InvalidOperationException), typeof(string));
            }
            Il.Newobj(constructor);
            Il.Throw();
            Il.MarkLabel(bigEnoughLabel);
        }
 /// <summary>
 ///     Loads &amp;<c>data</c>[<c>index</c>] onto the evaluation stack
 /// </summary>
 public void GoToCurrentLocation()
 {
     LoadData();  // stack: [pinnedData]
     LoadIndex(); // stack: [pinnedData, index]
     Il.Add();    // stack: [pinnedData + index]
 }
 /// <summary>
 ///     Loads &amp;<c>result</c>[<c>index</c>] onto the evaluation stack
 /// </summary>
 public void GoToCurrentLocation()
 {
     LoadResult(); // stack: [result]
     LoadIndex();  // stack: [result, index]
     Il.Add();     // stack: [result + index]
 }