示例#1
0
        public Block Compress(Block inputBlock, DecompressionHelpMode decompressionHelpMode)
        {
            if (inputBlock.Bytes.Count == 0)
            {
                return(new Block(EmptyBytes, inputBlock.Offset));
            }

            using (var memoryStream = new MemoryStream())
            {
                using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Compress, true))
                {
                    // ReSharper disable once AssignNullToNotNullAttribute
                    gZipStream.Write(inputBlock.Bytes.Array, inputBlock.Bytes.Offset, inputBlock.Bytes.Count);
                }

                var compressedBytes = memoryStream.ToArray();
                var buffer          = new ArraySegment <byte>(compressedBytes, 0, (int)memoryStream.Position);

                if (decompressionHelpMode == DecompressionHelpMode.BlockLengthInMimetypeSection)
                {
                    GzipHeader.FindFirst(buffer)?.SetMimetypeBytes(BitConverter.GetBytes(buffer.Count));
                }

                return(new Block(buffer, inputBlock.Offset));
            }
        }
示例#2
0
            public void Should_return_null_when_bytes_does_not_contain_gzip_header()
            {
                var bytes = TestData.ShortFileContent.ToArraySegment();

                var result = GzipHeader.FindFirst(bytes);

                result.Should().BeNull();
            }
示例#3
0
            public void Should_return_gzip_header_when_bytes_have_size_exactly_equal_to_header()
            {
                var bytes = TestData.ShortFileContent.GzipCompress().TakeFirst(GzipHeader.Length);

                var result = GzipHeader.FindFirst(bytes);

                result.Should().NotBeNull();
                result.Value.Position.Should().Be(0);
            }
示例#4
0
            public void Should_return_gzip_header_when_bytes_starts_with_gzip_header()
            {
                var bytes = TestData.ShortFileContent.GzipCompress();

                var result = GzipHeader.FindFirst(bytes);

                result.Should().NotBeNull();
                result.Value.Position.Should().Be(0);
            }
示例#5
0
            public void Should_set_length_into_mime_type_section_when_enabled_set_length_to_mimetype()
            {
                var originalString = TestData.InputFileContent;
                var originalBytes  = originalString.ToArraySegment();
                var block          = new Block(originalBytes, 100);

                var compressedBlock = gzipBlockCompression.Compress(block, DecompressionHelpMode.BlockLengthInMimetypeSection);

                var mimetype = GzipHeader.FindFirst(compressedBlock.Bytes).Value.MimetypeBytes.ToArray();

                BitConverter.ToInt32(mimetype).Should().Be(compressedBlock.Bytes.Count);
            }
示例#6
0
            public void Should_return_null_when_given_segment_have_less_count_than_header_required()
            {
                var someUncompressedBytes = TestData.ShortFileContent.ToBytes();
                var firstCompressed       = TestData.ShortFileContent.GzipCompress();
                var bytes = someUncompressedBytes.Concat(firstCompressed)
                            .ToArray()
                            .Segment(someUncompressedBytes.Length, 8);

                var result = GzipHeader.FindFirst(bytes);

                result.Should().BeNull();
            }
示例#7
0
            public void Should_return_gzip_header_when_it_first_occurence_not_from_start_of_bytes()
            {
                var someUncompressedBytes = TestData.ShortFileContent.ToBytes();
                var bytes = someUncompressedBytes.Concat(TestData.ShortFileContent.GzipCompress())
                            .Concat(TestData.ShortFileContent.GzipCompress())
                            .ToArray()
                            .ToSegment();

                var result = GzipHeader.FindFirst(bytes);

                result.Should().NotBeNull();
                result.Value.Position.Should().Be(someUncompressedBytes.Length);
            }
示例#8
0
            public void Should_set_position_of_found_header_with_respecting_segment_offset()
            {
                var uncompressedBytes = TestData.ShortFileContent.ToBytes();
                var firstCompressed   = TestData.ShortFileContent.GzipCompress();
                var secondCompressed  = TestData.ShortFileContent.GzipCompress();
                var bytes             = uncompressedBytes
                                        .Concat(firstCompressed)
                                        .Concat(secondCompressed)
                                        .ToArray()
                                        .Segment(uncompressedBytes.Length + 3);

                var result = GzipHeader.FindFirst(bytes);

                result.Should().NotBeNull();
                result.Value.Position.Should().Be(uncompressedBytes.Length + firstCompressed.Count);
            }
示例#9
0
        public IEnumerable <SplitResult> SplitToIndependentBlocks(RewindableReadonlyStream inputStream)
        {
            long GetCurrentHeaderPosition(ArraySegment <byte> headerBytes)
            {
                return(inputStream.Position - headerBytes.Offset);
            }

            Result <int, GzipSplittingStatus?> GetBlockLengthFromGzipHeader(ArraySegment <byte> headerBytes)
            {
                var header = GzipHeader.FindFirst(headerBytes);

                if (header == null)
                {
                    return(GzipSplittingStatus.WrongFormat);
                }

                var length = header.Value.GetMimetypeAsInt();

                if (length == 0)
                {
                    return(GzipSplittingStatus.CantReadBlock);
                }

                if (length > blockSizeLimit)
                {
                    log.Info($"Block size {length} at offset {GetCurrentHeaderPosition(headerBytes)} is greater than limit {blockSizeLimit}");
                    return(GzipSplittingStatus.CantReadBlock);
                }

                return(length);
            }

            (int length, ArraySegment <byte> readBytes, bool endOfStream, GzipSplittingStatus?error) ReadCurrentGzipBlockLengthFromStream()
            {
                var length = 0;
                GzipSplittingStatus?readLengthError = null;

                var bytes = new byte[GzipHeader.Length];

                var(headerBytes, isEndOfStream) = inputStream.ReadExactBuffer(bytes);
                if (headerBytes.Count < bytes.Length)
                {
                    if (!isEndOfStream)
                    {
                        readLengthError = GzipSplittingStatus.WrongFormat;
                    }
                }
                else
                {
                    (length, readLengthError) = GetBlockLengthFromGzipHeader(headerBytes);
                }

                return(length, headerBytes, isEndOfStream, readLengthError);
            }

            var currentBlockPoistion = inputStream.Position;

            var(blockLength, headerReadBytes, endOfStream, error) = ReadCurrentGzipBlockLengthFromStream();
            if (headerReadBytes.Count > 0)
            {
                inputStream.ReturnTailOfReadedBytes(headerReadBytes);
            }
            if (error.HasValue)
            {
                yield return(error.Value);

                yield break;
            }

            while (!endOfStream)
            {
                ArraySegment <byte> buffer;
                var blockAndNextHeaderLength = blockLength + GzipHeader.Length;
                (buffer, endOfStream) = inputStream.ReadExactFullBuffer(blockAndNextHeaderLength);
                if (!endOfStream && buffer.Count == 0)
                {
                    log.Info($"Block hader at offset {currentBlockPoistion} contain invalid length or non length in mime type");
                    yield return(GzipSplittingStatus.CantReadBlock);

                    yield break;
                }
                currentBlockPoistion = inputStream.Position;

                ArraySegment <byte> independentBlockBytes;
                var nextBlockLength = 0;
                GzipSplittingStatus?nextHeaderError = null;
                if (buffer.Count == blockLength && endOfStream)
                {
                    independentBlockBytes = buffer;
                }
                else if (buffer.Count == blockAndNextHeaderLength)
                {
                    var headerBytes = buffer.SliceFromEnd(GzipHeader.Length);
                    (nextBlockLength, nextHeaderError) = GetBlockLengthFromGzipHeader(headerBytes);
                    if (nextHeaderError != GzipSplittingStatus.WrongFormat)
                    {
                        inputStream.ReturnTailOfReadedBytes(headerBytes);
                        independentBlockBytes = buffer.RemoveFromEnd(GzipHeader.Length);
                    }
                }

                if (independentBlockBytes.Count == 0)
                {
                    inputStream.ReturnTailOfReadedBytes(buffer);
                    yield return(GzipSplittingStatus.CantReadBlock);

                    yield break;
                }

                yield return(new IndependentGzipBlock(WrapBufferWithStream(independentBlockBytes)));

                if (nextHeaderError.HasValue)
                {
                    yield return(nextHeaderError.Value);

                    yield break;
                }

                blockLength = nextBlockLength;
            }

            yield return(GzipSplittingStatus.StreamIsEnd);
        }
示例#10
0
 private static void SetLengthToHeader(byte[] bytes, int length)
 {
     // ReSharper disable once PossibleInvalidOperationException
     GzipHeader.FindFirst(bytes).Value.SetMimetypeBytes(BitConverter.GetBytes(length));
 }