private static ReadBuffer UnpackPass(ReadBuffer packedData)
        {
            switch (packedData[0])
            {
            case 1:
                return(UnpackRLE(packedData.Drop(8)));

            case 2:
                return(UnpackVLE(packedData.Drop(4)));

            default:
                throw new ArgumentException("Unknown compression type!");
            }
        }
        public static byte[] Unpack(byte[] packedData)
        {
            var  buffer     = new ReadBuffer(packedData);
            bool singlePass = (buffer[0] & 0x80) == 0;
            int  passCount  = singlePass ? 1 : buffer[0] & 0x7f;

            ReadBuffer currentPass = singlePass ? buffer : buffer.Drop(4);

            for (int i = 0; i < passCount; i++)
            {
                currentPass = UnpackPass(currentPass);
            }

            return(currentPass.ToArray());
        }
        private static ReadBuffer UnpackRLE(ReadBuffer packedData)
        {
            int escCount  = packedData[0] & 0x7f;
            var escCodes  = packedData.Slice(1, escCount);
            var rleData   = packedData.Drop(escCount + 1);
            var escLookup = new byte[0x100];

            for (int i = 0; i < escCount; i++)
            {
                escLookup[escCodes[i]] = (byte)(i + 1);
            }

            bool compressed  = (packedData[0] & 0x80) == 0;
            var  encodedData = compressed ? UnpackSequences(rleData, escCodes[1]) : rleData;

            var result = new WriteBuffer();

            while (encodedData.Length > 0)
            {
                var code = escLookup[encodedData[0]];
                switch (code)
                {
                case 0:
                    result.Append(encodedData[0]);
                    encodedData = encodedData.Drop(1);
                    break;

                case 1:
                    result.AppendRepeat(encodedData[2], encodedData[1]);
                    encodedData = encodedData.Drop(3);
                    break;

                case 3:
                    result.AppendRepeat(encodedData[3], encodedData[1] + (((int)encodedData[2]) << 8));
                    encodedData = encodedData.Drop(4);
                    break;

                default:
                    result.AppendRepeat(encodedData[1], code - 1);
                    encodedData = encodedData.Drop(2);
                    break;
                }
            }

            return(result.ToReadBuffer());
        }
        private static ReadBuffer UnpackVLE(ReadBuffer packedData)
        {
            var widthsCount   = packedData[0];
            var widths        = packedData.Slice(1, widthsCount);
            var alphabetCount = widths.Select(val => (int)val).Sum();
            var alphabet      = packedData.Slice(1 + widthsCount, alphabetCount);

            var dictionary = new HuffmanTree(widths, alphabet);
            var stream     = EnumerateBits(packedData.Drop(1 + widthsCount + alphabetCount));

            var result = new WriteBuffer();

            while (true)
            {
                int value = dictionary.DecodeByte(stream);
                if (value < 0)
                {
                    break;
                }
                result.Append((byte)value);
            }

            return(result.ToReadBuffer());
        }