/// <summary>Reads the next chunk from stream.</summary> /// <returns><c>true</c> if next has been read, or <c>false</c> if it is legitimate end of file. /// Throws <see cref="EndOfStreamException"/> if end of stream was unexpected.</returns> private bool AcquireNextChunk() { do { ulong varint; if (!TryReadVarInt(out varint)) { return(false); } var flags = (ChunkFlags)varint; var isCompressed = (flags & ChunkFlags.Compressed) != 0; var originalLength = (int)ReadVarInt(); var compressedLength = isCompressed ? (int)ReadVarInt() : originalLength; if (compressedLength > originalLength) { throw EndOfStream(); // corrupted } if (compressedDataBuffer == null || compressedDataBuffer.Length < compressedLength) { compressedDataBuffer = new byte[compressedLength]; } var chunk = ReadBlock(compressedDataBuffer, 0, compressedLength); if (chunk != compressedLength) { throw EndOfStream(); // currupted } if (!isCompressed) { // swap the buffers var oldDataBuffer = dataBuffer; dataBuffer = compressedDataBuffer; // no compression on this chunk compressedDataBuffer = oldDataBuffer; // ensure that compressedDataBuffer and dataBuffer are different bufferLength = compressedLength; } else { if (dataBuffer == null || dataBuffer.Length < originalLength) { dataBuffer = new byte[originalLength]; } var passes = (int)flags >> 2; if (passes != 0) { throw new NotSupportedException("Chunks with multiple passes are not supported."); } LZ4Codec.Decode(compressedDataBuffer, 0, compressedLength, dataBuffer, 0, originalLength, true); bufferLength = originalLength; } bufferOffset = 0; } while (bufferLength == 0); // skip empty block (shouldn't happen but...) return(true); }