 
     private static func processIndex(_ blockInfos: [(unpaddedSize: Int, uncompSize: Int)],
                                      _ pointerData: DataWithPointer) throws -> Int {
-        var indexBytes: [UInt8] = [0x00]
-        let numberOfRecordsTuple = try pointerData.multiByteDecode()
-        indexBytes.append(contentsOf: numberOfRecordsTuple.bytesProcessed)
-        let numberOfRecords = numberOfRecordsTuple.multiByteInteger
-        guard numberOfRecords == blockInfos.count
+        let indexStartIndex = pointerData.index - 1
+        let recordsCount = try pointerData.multiByteDecode()
+        guard recordsCount == blockInfos.count
             else { throw XZError.wrongFieldValue }
+
         for blockInfo in blockInfos {
-            let unpaddedSizeTuple = try pointerData.multiByteDecode()
-            guard unpaddedSizeTuple.multiByteInteger == blockInfo.unpaddedSize
+            let unpaddedSize = try pointerData.multiByteDecode()
+            guard unpaddedSize == blockInfo.unpaddedSize
                 else { throw XZError.wrongFieldValue }
-            indexBytes.append(contentsOf: unpaddedSizeTuple.bytesProcessed)
-
-            let uncompSizeTuple = try pointerData.multiByteDecode()
-            guard uncompSizeTuple.multiByteInteger == blockInfo.uncompSize
+
+            let uncompSize = try pointerData.multiByteDecode()
+            guard uncompSize == blockInfo.uncompSize
                 else { throw XZError.wrongDataSize }
-            indexBytes.append(contentsOf: uncompSizeTuple.bytesProcessed)
-        }
-
-        if indexBytes.count % 4 != 0 {
-            let paddingSize = 4 - indexBytes.count % 4
+        }
+
+        var indexSize = pointerData.index - indexStartIndex
+        if indexSize % 4 != 0 {
+            let paddingSize = 4 - indexSize % 4
             for _ in 0..<paddingSize {
                 let byte = pointerData.byte()
                 guard byte == 0x00
                     else { throw XZError.wrongPadding }
-                indexBytes.append(byte)
+                indexSize += 1
             }
         }
 
         let indexCRC = pointerData.uint32()
-        guard CheckSums.crc32(indexBytes) == indexCRC
+        pointerData.index = indexStartIndex
+        guard CheckSums.crc32(pointerData.bytes(count: indexSize)) == indexCRC
             else { throw XZError.wrongInfoCRC }
-
-        return indexBytes.count + 4
-    }
-
-    private static func processFooter(_ streamHeader: (checkType: UInt8, flagsCRC: UInt32),
+        pointerData.index += 4
+
+        return indexSize + 4
+    }
+
+    private static func processFooter(_ streamHeader: (checkType: Int, flagsCRC: UInt32),
                                       _ indexSize: Int,
                                       _ pointerData: DataWithPointer) throws {
         let footerCRC = pointerData.uint32()
-        let storedBackwardSize = pointerData.bytes(count: 4)
-        let footerStreamFlags = pointerData.bytes(count: 2)
-        guard CheckSums.crc32([storedBackwardSize, footerStreamFlags].flatMap { $0 }) == footerCRC
+        /// Indicates the size of Index field. Should match its real size.
+        let backwardSize = (pointerData.uint32().toInt() + 1 ) * 4
+        let streamFooterFlags = pointerData.uint16().toInt()
+
+        pointerData.index -= 6
+        guard CheckSums.crc32(pointerData.bytes(count: 6)) == footerCRC
             else { throw XZError.wrongInfoCRC }
 
-        /// Indicates the size of Index field. Should match its real size.
-        var realBackwardSize = 0
-        for i in 0..<4 {
-            realBackwardSize |= storedBackwardSize[i].toInt() << (8 * i)
-        }
-        realBackwardSize += 1
-        realBackwardSize *= 4
-        guard realBackwardSize == indexSize
+        guard backwardSize == indexSize
             else { throw XZError.wrongFieldValue }
 
         // Flags in the footer should be the same as in the header.
-        guard footerStreamFlags[0] == 0
+        guard streamFooterFlags & 0xFF == 0
             else { throw XZError.fieldReservedValue }
-        guard footerStreamFlags[1] & 0x0F == streamHeader.checkType
+        guard (streamFooterFlags & 0xF00) >> 8 == streamHeader.checkType
             else { throw XZError.wrongFieldValue }
-        guard footerStreamFlags[1] & 0xF0 == 0
+        guard streamFooterFlags & 0xF000 == 0
             else { throw XZError.fieldReservedValue }
 
         // Check footer's magic number

        return (checkType, flagsCRC)
    }

    private static func processBlock(_ blockHeaderSize: UInt8,
                                     _ pointerData: DataWithPointer) throws -> (blockData: [UInt8], unpaddedSize: Int, uncompressedSize: Int) {
        var blockBytes: [UInt8] = []
        let blockHeaderStartIndex = pointerData.index - 1
        blockBytes.append(blockHeaderSize)
        guard blockHeaderSize >= 0x01 && blockHeaderSize <= 0xFF
            else { throw XZError.wrongFieldValue }
        let realBlockHeaderSize = (blockHeaderSize + 1) * 4

        let blockFlags = pointerData.byte()
        blockBytes.append(blockFlags)
        /**
         Bit values 00, 01, 10, 11 indicate filters number from 1 to 4,
         so we actually need to add 1 to get filters' number.

        return Data(bytes: out)
    }

    private static func processStreamHeader(_ pointerData: DataWithPointer) throws -> (checkType: Int, flagsCRC: UInt32) {
        // Check magic number.
        guard pointerData.bytes(count: 6) == [0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00]
            else { throw XZError.wrongMagic }
