public static int Uncompress(byte[] compressed, int compressedOffset, int compressedSize, byte[] uncompressed, int uncompressedOffset)
        {
            // Read the uncompressed length from the front of the compressed input
            int[] varInt         = ReadUncompressedLength(compressed, compressedOffset);
            int   expectedLength = varInt[0];

            compressedOffset += varInt[1];
            compressedSize   -= varInt[1];

            SnappyInternalUtils.CheckArgument(expectedLength <= uncompressed.Length - uncompressedOffset,
                                              "Uncompressed length {0} must be less than {1}", expectedLength,
                                              uncompressed.Length - uncompressedOffset);

            // Process the entire input
            int uncompressedSize = DecompressAllTags(
                compressed,
                compressedOffset,
                compressedSize,
                uncompressed,
                uncompressedOffset);

            if (!(expectedLength == uncompressedSize))
            {
                throw new CorruptionException(string.Format("Recorded length is {0} bytes but actual length after decompression is {1} bytes ",
                                                            expectedLength,
                                                            uncompressedSize));
            }

            return(expectedLength);
        }
        private static void IncrementalCopyFastPath(byte[] output, int srcIndex, int opIndex, int length)
        {
            int copiedLength = 0;

            while ((opIndex + copiedLength) - srcIndex < 8)
            {
                SnappyInternalUtils.CopyLong(output, srcIndex, output, opIndex + copiedLength);
                copiedLength += (opIndex + copiedLength) - srcIndex;
            }

            for (int i = 0; i < length - copiedLength; i += 8)
            {
                SnappyInternalUtils.CopyLong(output, srcIndex + i, output, opIndex + copiedLength + i);
            }
        }
        private static void CopyLiteral(byte[] input, int ipIndex, byte[] output, int opIndex, int length)
        {
            int spaceLeft     = output.Length - opIndex;
            int readableBytes = input.Length - ipIndex;

            if (readableBytes < length || spaceLeft < length)
            {
                throw new CorruptionException("Corrupt literal length");
            }

            if (length <= 16 && spaceLeft >= 16 && readableBytes >= 16)
            {
                SnappyInternalUtils.CopyLong(input, ipIndex, output, opIndex);
                SnappyInternalUtils.CopyLong(input, ipIndex + 8, output, opIndex + 8);
            }
            else
            {
                var fastLength = (int)(((uint)length) & 0xFFFFFFF8);
                if (fastLength <= 64)
                {
                    // copy long-by-long
                    for (int i = 0; i < fastLength; i += 8)
                    {
                        SnappyInternalUtils.CopyLong(input, ipIndex + i, output, opIndex + i);
                    }

                    // copy byte-by-byte
                    int slowLength = length & 0x7;
                    // NOTE: This is not a manual array copy.  We are copying an overlapping region
                    // and we want input data to repeat as it is recopied. see incrementalCopy below.
                    //noinspection ManualArrayCopy
                    for (int i = 0; i < slowLength; i += 1)
                    {
                        output[opIndex + fastLength + i] = input[ipIndex + fastLength + i];
                    }
                }
                else
                {
                    SnappyInternalUtils.CopyMemory(input, ipIndex, output, opIndex, length);
                }
            }
        }
 private static int ReadTrailer(byte[] data, int index, int bytes)
 {
     return(SnappyInternalUtils.LoadInt(data, index) & _wordmask[bytes]);
 }
        /// <summary>
        ///  This is a second copy of the inner loop of decompressTags used when near the
        ///  end of the input. The key difference is the reading of the trailer bytes. The
        ///  fast code does a blind read of the next 4 bytes as an int, and this code
        ///  assembles the int byte-by-byte to assure that the array is not over run. The
        ///  reason this code path is separate is the if condition to choose between these
        ///  two seemingly small differences costs like 10-20% of the throughput. I'm
        ///  hoping in future' versions of hot-spot this code can be integrated into the
        ///  main loop but for now it is worth the extra maintenance pain to get the extra
        ///  10-20%.
        /// </summary>
        private static int[] DecompressTagSlow(byte[] input, int ipIndex, byte[] output, int outputLimit, int outputOffset, int opIndex)
        {
            // read the op code
            int opCode       = SnappyInternalUtils.LoadByte(input, ipIndex++);
            int entry        = SnappyInternalUtils.LookupShort(_opLookupTable, opCode);
            var trailerBytes = (int)((uint)entry >> 11);
            //
            // Key difference here
            //
            int trailer = 0;

            switch (trailerBytes)
            {
            case 4:
                trailer = (input[ipIndex + 3] & 0xff) << 24;
                goto case 3;

            case 3:
                trailer |= (input[ipIndex + 2] & 0xff) << 16;
                goto case 2;

            case 2:
                trailer |= (input[ipIndex + 1] & 0xff) << 8;
                goto case 1;

            case 1:
                trailer |= (input[ipIndex] & 0xff);
                break;
            }

            // advance the ipIndex past the op codes
            ipIndex += trailerBytes;
            int length = entry & 0xff;

            if ((opCode & 0x3) == Literal)
            {
                int literalLength = length + trailer;
                CopyLiteral(input, ipIndex, output, opIndex, literalLength);
                ipIndex += literalLength;
                opIndex += literalLength;
            }
            else
            {
                // copyOffset/256 is encoded in bits 8..10.  By just fetching
                // those bits, we get copyOffset (since the bit-field starts at
                // bit 8).
                int copyOffset = entry & 0x700;
                copyOffset += trailer;

                // inline to force hot-spot to keep inline
                {
                    int spaceLeft = outputLimit - opIndex;
                    int srcIndex  = opIndex - copyOffset;

                    if (srcIndex < outputOffset)
                    {
                        throw new CorruptionException("Invalid copy offset for opcode starting at " + (ipIndex - trailerBytes - 1));
                    }

                    if (length <= 16 && copyOffset >= 8 && spaceLeft >= 16)
                    {
                        // Fast path, used for the majority (70-80%) of dynamic invocations.
                        SnappyInternalUtils.CopyLong(output, srcIndex, output, opIndex);
                        SnappyInternalUtils.CopyLong(output, srcIndex + 8, output, opIndex + 8);
                    }
                    else if (spaceLeft >= length + MaxIncrementCopyOverflow)
                    {
                        IncrementalCopyFastPath(output, srcIndex, opIndex, length);
                    }
                    else
                    {
                        IncrementalCopy(output, srcIndex, output, opIndex, length);
                    }
                }
                opIndex += length;
            }
            return(new[] { ipIndex, opIndex });
        }
        private static int DecompressAllTags(
            byte[] input,
            int inputOffset,
            int inputSize,
            byte[] output,
            int outputOffset)
        {
            int outputLimit = output.Length;

            int ipLimit = inputOffset + inputSize;
            int opIndex = outputOffset;
            int ipIndex = inputOffset;

            while (ipIndex < ipLimit - 5)
            {
                int opCode       = SnappyInternalUtils.LoadByte(input, ipIndex++);
                int entry        = SnappyInternalUtils.LookupShort(_opLookupTable, opCode);
                var trailerBytes = (int)((uint)entry >> 11);
                int trailer      = ReadTrailer(input, ipIndex, trailerBytes);

                // advance the ipIndex past the op codes
                ipIndex += (int)((uint)entry >> 11);
                int length = entry & 0xff;

                if ((opCode & 0x3) == Literal)
                {
                    int literalLength = length + trailer;
                    CopyLiteral(input, ipIndex, output, opIndex, literalLength);
                    ipIndex += literalLength;
                    opIndex += literalLength;
                }
                else
                {
                    // copyOffset/256 is encoded in bits 8..10.  By just fetching
                    // those bits, we get copyOffset (since the bit-field starts at
                    // bit 8).
                    int copyOffset = entry & 0x700;
                    copyOffset += trailer;

                    // inline to force hot-spot to keep inline
                    //
                    // Equivalent to incrementalCopy (below) except that it can write up to ten extra
                    // bytes after the end of the copy, and that it is faster.
                    //
                    // The main part of this loop is a simple copy of eight bytes at a time until
                    // we've copied (at least) the requested amount of bytes.  However, if op and'
                    // src are less than eight bytes apart (indicating a repeating pattern of
                    // length < 8), we first need to expand the pattern in order to get the correct
                    // results. For instance, if the buffer looks like this, with the eight-byte
                    // <src> and <op> patterns marked as intervals:
                    //
                    //    abxxxxxxxxxxxx
                    //    [------]           src
                    //      [------]         op
                    //
                    // a single eight-byte copy from <src> to <op> will repeat the pattern once,
                    // after which we can move <op> two bytes without moving <src>:
                    //
                    //    ababxxxxxxxxxx
                    //    [------]           src
                    //        [------]       op
                    //
                    // and repeat the exercise until the two no longer overlap.
                    //
                    // This allows us to do very well in the special case of one single byte
                    // repeated many times, without taking a big hit for more general cases.
                    //
                    // The worst case of extra writing past the end of the match occurs when
                    // op - src == 1 and len == 1; the last copy will read from byte positions
                    // [0..7] and write to [4..11], whereas it was only supposed to write to
                    // position 1. Thus, ten excess bytes.
                    {
                        int spaceLeft = outputLimit - opIndex;
                        int srcIndex  = opIndex - copyOffset;
                        if (srcIndex < outputOffset)
                        {
                            throw new CorruptionException("Invalid copy offset for opcode starting at " + (ipIndex - trailerBytes - 1));
                        }

                        if (length <= 16 && copyOffset >= 8 && spaceLeft >= 16)
                        {
                            // Fast path, used for the majority (70-80%) of dynamic invocations.
                            SnappyInternalUtils.CopyLong(output, srcIndex, output, opIndex);
                            SnappyInternalUtils.CopyLong(output, srcIndex + 8, output, opIndex + 8);
                        }
                        else if (spaceLeft >= length + MaxIncrementCopyOverflow)
                        {
                            IncrementalCopyFastPath(output, srcIndex, opIndex, length);
                        }
                        else
                        {
                            IncrementalCopy(output, srcIndex, output, opIndex, length);
                        }
                    }
                    opIndex += length;
                }
            }


            for (; ipIndex < ipLimit;)
            {
                int[] result = DecompressTagSlow(input, ipIndex, output, outputLimit, outputOffset, opIndex);
                ipIndex = result[0];
                opIndex = result[1];
            }

            return(opIndex - outputOffset);
        }