 
         // STREAM HEADER
 
+        let streamHeader = try processStreamHeader(&pointerData)
+
+        // BLOCKS
+        try processBlock(&pointerData)
+
+        // INDEX
+
+        // STREAM FOOTER (Should be after parsing blocks).
+        try processFooter(streamHeader, &pointerData)
+
+        // STREAM PADDING
+        var paddingBytes = 0
+        while true {
+            let byte = pointerData.alignedByte()
+            if byte != 0 {
+                if paddingBytes % 4 != 0 {
+                    throw XZError.WrongStreamPadding
+                } else {
+                    break
+                }
+            }
+            paddingBytes += 1
+        }
+        pointerData.index -= 1
+
+        return try LZMA.decompress(&pointerData)
+    }
+
+    private static func processStreamHeader(_ pointerData: inout DataWithPointer) throws -> StreamHeader {
         // Check magic number.
         guard pointerData.intFromAlignedBytes(count: 6) == 0x005A587A37FD
             else { throw XZError.WrongMagic }

    case WrongFooterCRC
    /// Size of stream padding was not multiple of four.
    case WrongStreamPadding
}

/// A class with unarchive function for xz archives.
public class XZArchive: Archive {

    struct ServiceInfo {

    }

    /**

        guard CheckSums.crc32([0, checkType.toUInt8()]) == flagsCRC
            else { throw XZError.WrongFlagsCRC }

        return StreamHeader(checkType: checkType, flagsCRC: flagsCRC)
    }

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

        let blockFlags = pointerData.alignedByte()
        blockBytes.append(blockFlags)
        let numberOfFilters = blockFlags & 0x03
        guard blockFlags & 0x3C == 0
            else { throw XZError.WrongBlockFlags }

        /// Should match size of compressed data.
        var compressedSize = -1
        if blockFlags & 0x40 != 0 {
            let compressedSizeDecodeResult = try pointerData.multiByteDecode()
            compressedSize = compressedSizeDecodeResult.multiByteInteger
            guard compressedSize > 0
                else { throw XZError.WrongCompressedSize }
            blockBytes.append(contentsOf: compressedSizeDecodeResult.bytesProcessed)
        }

        /// Should match the size of data after decompression.
        var uncompressedSize = -1
        if blockFlags & 0x80 != 0 {
            let uncompressedSizeDecodeResult = try pointerData.multiByteDecode()
            uncompressedSize = uncompressedSizeDecodeResult.multiByteInteger
            guard uncompressedSize > 0
                else { throw XZError.WrongUncompressedSize }
            blockBytes.append(contentsOf: uncompressedSizeDecodeResult.bytesProcessed)
        }

        for _ in 0..<numberOfFilters {
            //            let filterID = try multiByteDecode(&pointerData)
            //            guard filterID < 0x4000000000000000 else { throw XZError.WrongFilterID }
            //            let sizeOfProperties = try multiByteDecode(&pointerData)
            // TODO: Add parsing of filters' properties.
            // Don't forget to add this bytes to blockBytes
        }

        while pointerData.index - blockHeaderStartIndex < blockHeaderSize.toInt() {
            let byte = pointerData.alignedByte()
            blockBytes.append(byte)
            if byte != 0x00 {
                throw XZError.WrongBlockHeaderPadding
            }
        }

        let blockHeaderCRC = pointerData.intFromAlignedBytes(count: 4)
        guard CheckSums.crc32(blockBytes) == blockHeaderCRC
            else { throw XZError.WrongBlocksCRC }
    }

    private static func processFooter(_ streamHeader: StreamHeader,
                                      _ pointerData: inout DataWithPointer) throws {
        let footerCRC = pointerData.intFromAlignedBytes(count: 4)
        let storedBackwardSize = pointerData.alignedBytes(count: 4)
        let footerStreamFlags = pointerData.alignedBytes(count: 2)
