public uint FastStreamEncoder(int blockLength, int sourceLength, int extraBlocks = 0)
        {
            sourceLength = Mem.RoundUp(sourceLength, blockLength);
            var targetLength = 2 * sourceLength;

            var source = new byte[sourceLength];
            var target = new byte[targetLength];

            Lorem.Fill(source, 0, source.Length);

            using (var encoder = new LZ4FastEncoder(blockLength, extraBlocks))
            {
                var sourceP = 0;
                var targetP = 0;

                while (sourceP < sourceLength && targetP < targetLength)
                {
                    encoder.TopupAndEncode(
                        source, sourceP, Math.Min(blockLength, sourceLength - sourceP),
                        target, targetP, targetLength - targetP,
                        true, false,
                        out var loaded,
                        out var encoded);
                    sourceP += loaded;
                    targetP += encoded;
                }

                return(Tools.Adler32(target, 0, targetP));
            }
        }
        private static byte[] Encode(byte[] input, int topupSize, int blockSize, int extraBlocks)
        {
            using (var outputStream = new MemoryStream())
                using (var inputStream = new MemoryStream(input))
                {
                    using (var inputReader = new BinaryReader(inputStream, Encoding.UTF8, false))
                        using (var outputWriter = new BinaryWriter(outputStream, Encoding.UTF8, true))
                            using (var encoder = new LZ4FastEncoder(blockSize, extraBlocks))
                            {
                                var inputBuffer  = new byte[topupSize];
                                var outputBuffer = new byte[LZ4Codec.MaximumOutputSize(encoder.BlockSize)];

                                while (true)
                                {
                                    var bytes = inputReader.Read(inputBuffer, 0, inputBuffer.Length);

                                    if (bytes == 0)
                                    {
                                        Flush(outputWriter, encoder, outputBuffer);
                                        outputWriter.Write(-1);
                                        break;
                                    }

                                    Write(outputWriter, encoder, inputBuffer, bytes, outputBuffer);
                                }
                            }

                    return(outputStream.ToArray());
                }
        }
        public void HighEntropyRepeated()
        {
            var random  = new Random(0);
            var encoder = new LZ4FastEncoder(256);
            var source  = new byte[256];

            random.NextBytes(source);
            var target = new byte[1024];

            Assert.Equal(256, encoder.Topup(source, 0, 256));
            Assert.Equal(-256, encoder.Encode(target, 0, 1024, true));

            Assert.Equal(256, encoder.Topup(source, 0, 256));
            Assert.True(encoder.Encode(target, 0, 1024, true) < 32);
        }