< Summary

Information
Class: System.IO.Compression.DeflateStream
Assembly: System.IO.Compression
File(s): D:\runner\runtime\src\libraries\System.IO.Compression\src\System\IO\Compression\DeflateZLib\DeflateStream.cs
Line coverage
60%
Covered lines: 408
Uncovered lines: 271
Coverable lines: 679
Total lines: 1149
Line coverage: 60%
Branch coverage
55%
Covered branches: 143
Total branches: 259
Branch coverage: 55.2%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)100%11100%
.ctor(...)100%110%
.ctor(...)100%110%
.ctor(...)100%110%
.ctor(...)100%11100%
.ctor(...)100%110%
.ctor(...)100%110%
.ctor(...)33.33%6673.33%
.ctor(...)100%11100%
InitializeDeflater(...)50%2290%
GetZLibNativeCompressionLevel(...)20%5550%
GetMemLevel(...)50%22100%
InitializeBuffer()100%11100%
EnsureBufferInitialized()100%22100%
Flush()0%220%
FlushAsync(...)0%440%
Core(System.Threading.CancellationToken)0%660%
Seek(...)100%110%
SetLength(...)100%110%
ReadByte()0%220%
Read(...)100%110%
Read(...)50%2271.42%
ReadCore(...)71.42%282868.29%
EnsureNotDisposed()100%11100%
EnsureDecompressionMode()50%2275%
ThrowCannotReadFromDeflateStreamException()100%110%
EnsureCompressionMode()50%2275%
ThrowCannotWriteToDeflateStreamException()100%110%
ThrowGenericInvalidData()100%110%
ThrowTruncatedInvalidData()100%110%
BeginRead(...)100%110%
EndRead(...)100%110%
ReadAsync(...)100%110%
ReadAsync(...)50%2271.42%
ReadAsyncMemory(...)50%2281.81%
Core(System.Memory`1<System.Byte>,System.Threading.CancellationToken)60.71%282863.41%
Write(...)100%110%
WriteByte(...)0%220%
Write(...)50%2266.66%
WriteCore(...)50%2287.5%
WriteDeflaterOutput()66.66%6672.72%
FlushBuffers()0%660%
PurgeBuffers(...)75%121286.66%
PurgeBuffersAsync()70%101092.3%
TryRewindStream(...)0%220%
Dispose(...)85.71%1414100%
DisposeAsync()50%22100%
Core()81.25%1616100%
BeginWrite(...)100%110%
EndWrite(...)100%110%
WriteAsync(...)100%110%
WriteAsync(...)50%2271.42%
WriteAsyncMemory(...)50%44100%
Core(System.ReadOnlyMemory`1<System.Byte>,System.Threading.CancellationToken)100%11100%
WriteDeflaterOutputAsync(...)66.66%6672.72%
CopyTo(...)50%22100%
CopyToAsync(...)50%4480%
.ctor(...)100%11100%
.ctor(...)100%11100%
CopyFromSourceToDestinationAsync()56.25%161665.62%
CopyFromSourceToDestination()56.25%161663.33%
WriteAsync(...)0%440%
WriteAsync(...)100%11100%
WriteAsyncCore(...)66.66%6680%
Write(...)60%101069.56%
Flush()100%110%
Read(...)100%110%
Seek(...)100%110%
SetLength(...)100%110%
EnsureNoActiveAsyncOperation()50%2250%
AsyncOperationStarting()50%2250%
AsyncOperationCompleting()100%11100%
ThrowInvalidBeginCall()100%110%
.cctor()50%22100%

File(s)

D:\runner\runtime\src\libraries\System.IO.Compression\src\System\IO\Compression\DeflateZLib\DeflateStream.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Buffers;
 5using System.Diagnostics;
 6using System.Diagnostics.CodeAnalysis;
 7using System.Runtime.InteropServices;
 8using System.Threading;
 9using System.Threading.Tasks;
 10using static System.IO.Compression.ZLibNative;
 11
 12namespace System.IO.Compression
 13{
 14    public partial class DeflateStream : Stream
 15    {
 16        private const int DefaultBufferSize = 8192;
 17
 18        private Stream _stream;
 19        private CompressionMode _mode;
 20        private bool _leaveOpen;
 21        private Inflater? _inflater;
 22        private Deflater? _deflater;
 23        private byte[]? _buffer;
 24        private volatile bool _activeAsyncOperation;
 25        private volatile bool _decompressionFinished;
 26
 150327        internal DeflateStream(Stream stream, CompressionMode mode, long uncompressedSize) : this(stream, mode, leaveOpe
 150328        {
 150329        }
 30
 031        public DeflateStream(Stream stream, CompressionMode mode) : this(stream, mode, leaveOpen: false)
 032        {
 033        }
 34
 035        public DeflateStream(Stream stream, CompressionMode mode, bool leaveOpen) : this(stream, mode, leaveOpen, ZLibNa
 036        {
 037        }
 38
 39        // Implies mode = Compress
 040        public DeflateStream(Stream stream, CompressionLevel compressionLevel) : this(stream, compressionLevel, leaveOpe
 041        {
 042        }
 43
 44        // Implies mode = Compress
 149445        public DeflateStream(Stream stream, CompressionLevel compressionLevel, bool leaveOpen) : this(stream, compressio
 149446        {
 149447        }
 48
 49        /// <summary>
 50        /// Initializes a new instance of the <see cref="DeflateStream"/> class by using the specified stream, compressi
 51        /// </summary>
 52        /// <param name="stream">The stream to which compressed data is written.</param>
 53        /// <param name="compressionOptions">The options for fine tuning the compression stream.</param>
 54        /// <param name="leaveOpen"><see langword="true" /> to leave the stream object open after disposing the <see cre
 55        /// <exception cref="ArgumentNullException"><paramref name="stream"/> or <paramref name="compressionOptions"/> i
 056        public DeflateStream(Stream stream, ZLibCompressionOptions compressionOptions, bool leaveOpen = false)
 057        {
 058            ArgumentNullException.ThrowIfNull(stream);
 059            ArgumentNullException.ThrowIfNull(compressionOptions);
 60
 061            int windowBits = CompressionFormatHelper.ResolveWindowBits(compressionOptions.WindowLog2, CompressionFormat.
 62
 063            InitializeDeflater(stream, (ZLibNative.CompressionLevel)compressionOptions.CompressionLevel, (CompressionStr
 064        }
 65
 066        internal DeflateStream(Stream stream, ZLibCompressionOptions compressionOptions, bool leaveOpen, int windowBits)
 067        {
 068            ArgumentNullException.ThrowIfNull(stream);
 069            ArgumentNullException.ThrowIfNull(compressionOptions);
 70
 071            InitializeDeflater(stream, (ZLibNative.CompressionLevel)compressionOptions.CompressionLevel, (CompressionStr
 072        }
 73
 74        /// <summary>
 75        /// Internal constructor to check stream validity and call the correct initialization function depending on
 76        /// the value of the CompressionMode given.
 77        /// </summary>
 150378        internal DeflateStream(Stream stream, CompressionMode mode, bool leaveOpen, int windowBits, long uncompressedSiz
 150379        {
 150380            ArgumentNullException.ThrowIfNull(stream);
 81
 150382            switch (mode)
 83            {
 84                case CompressionMode.Decompress:
 150385                    if (!stream.CanRead)
 086                        throw new ArgumentException(SR.NotSupported_UnreadableStream, nameof(stream));
 87
 150388                    _inflater = Inflater.CreateInflater(windowBits, uncompressedSize);
 150389                    _stream = stream;
 150390                    _mode = CompressionMode.Decompress;
 150391                    _leaveOpen = leaveOpen;
 150392                    break;
 93
 94                case CompressionMode.Compress:
 095                    InitializeDeflater(stream, ZLibNative.CompressionLevel.DefaultCompression, CompressionStrategy.Defau
 096                    break;
 97
 98                default:
 099                    throw new ArgumentException(SR.ArgumentOutOfRange_Enum, nameof(mode));
 100            }
 1503101        }
 102
 103        /// <summary>
 104        /// Internal constructor to specify the compressionLevel as well as the windowBits
 105        /// </summary>
 1494106        internal DeflateStream(Stream stream, CompressionLevel compressionLevel, bool leaveOpen, int windowBits)
 1494107        {
 1494108            ArgumentNullException.ThrowIfNull(stream);
 109
 1494110            InitializeDeflater(stream, GetZLibNativeCompressionLevel(compressionLevel), CompressionStrategy.DefaultStrat
 1494111        }
 112
 113        /// <summary>
 114        /// Sets up this DeflateStream to be used for Zlib Deflation/Compression
 115        /// </summary>
 116        [MemberNotNull(nameof(_stream))]
 117        internal void InitializeDeflater(Stream stream, ZLibNative.CompressionLevel compressionLevel, CompressionStrateg
 1494118        {
 1494119            Debug.Assert(stream != null);
 1494120            if (!stream.CanWrite)
 0121                throw new ArgumentException(SR.NotSupported_UnwritableStream, nameof(stream));
 122
 1494123            _deflater = Deflater.CreateDeflater(compressionLevel, strategy, windowBits, GetMemLevel(compressionLevel));
 124
 1494125            _stream = stream;
 1494126            _mode = CompressionMode.Compress;
 1494127            _leaveOpen = leaveOpen;
 1494128            InitializeBuffer();
 1494129        }
 130
 131        private static ZLibNative.CompressionLevel GetZLibNativeCompressionLevel(CompressionLevel compressionLevel) =>
 1494132            compressionLevel switch
 1494133            {
 1494134                CompressionLevel.Optimal => ZLibNative.CompressionLevel.DefaultCompression,
 0135                CompressionLevel.Fastest => ZLibNative.CompressionLevel.BestSpeed,
 0136                CompressionLevel.NoCompression => ZLibNative.CompressionLevel.NoCompression,
 0137                CompressionLevel.SmallestSize => ZLibNative.CompressionLevel.BestCompression,
 0138                _ => throw new ArgumentOutOfRangeException(nameof(compressionLevel)),
 1494139            };
 140
 141        private static int GetMemLevel(ZLibNative.CompressionLevel level) =>
 1494142            level == ZLibNative.CompressionLevel.NoCompression ?
 1494143                Deflate_NoCompressionMemLevel :
 1494144                Deflate_DefaultMemLevel;
 145
 146        [MemberNotNull(nameof(_buffer))]
 147        private void InitializeBuffer()
 2799148        {
 2799149            Debug.Assert(_buffer == null);
 2799150            _buffer = ArrayPool<byte>.Shared.Rent(DefaultBufferSize);
 2799151        }
 152
 153        [MemberNotNull(nameof(_buffer))]
 154        private void EnsureBufferInitialized()
 2601155        {
 2601156            if (_buffer == null)
 1305157            {
 1305158                InitializeBuffer();
 1305159            }
 2601160        }
 161
 162        public Stream BaseStream
 163        {
 164            get
 0165            {
 0166                EnsureNotDisposed();
 0167                return _stream;
 0168            }
 169        }
 170
 171        public override bool CanRead
 172        {
 173            get
 1503174            {
 1503175                if (_stream == null)
 0176                {
 0177                    return false;
 178                }
 179
 1503180                return (_mode == CompressionMode.Decompress && _stream.CanRead);
 1503181            }
 182        }
 183
 184        public override bool CanWrite
 185        {
 186            get
 0187            {
 0188                if (_stream == null)
 0189                {
 0190                    return false;
 191                }
 192
 0193                return (_mode == CompressionMode.Compress && _stream.CanWrite);
 0194            }
 195        }
 196
 1503197        public override bool CanSeek => false;
 198
 199        public override long Length
 200        {
 0201            get { throw new NotSupportedException(SR.NotSupported); }
 202        }
 203
 204        public override long Position
 205        {
 0206            get { throw new NotSupportedException(SR.NotSupported); }
 0207            set { throw new NotSupportedException(SR.NotSupported); }
 208        }
 209
 210        public override void Flush()
 0211        {
 0212            EnsureNotDisposed();
 0213            if (_mode == CompressionMode.Compress)
 0214                FlushBuffers();
 0215        }
 216
 217        public override Task FlushAsync(CancellationToken cancellationToken)
 0218        {
 0219            EnsureNoActiveAsyncOperation();
 0220            EnsureNotDisposed();
 221
 0222            if (cancellationToken.IsCancellationRequested)
 0223                return Task.FromCanceled(cancellationToken);
 224
 0225            return _mode != CompressionMode.Compress ?
 0226                Task.CompletedTask :
 0227                Core(cancellationToken);
 228
 229            async Task Core(CancellationToken cancellationToken)
 0230            {
 0231                AsyncOperationStarting();
 232                try
 0233                {
 0234                    Debug.Assert(_deflater != null && _buffer != null);
 235
 236                    // Compress any bytes left:
 0237                    await WriteDeflaterOutputAsync(cancellationToken).ConfigureAwait(false);
 238
 239                    // Pull out any bytes left inside deflater:
 240                    bool flushSuccessful;
 241                    do
 0242                    {
 243                        int compressedBytes;
 0244                        flushSuccessful = _deflater.Flush(_buffer, out compressedBytes);
 0245                        if (flushSuccessful)
 0246                        {
 0247                            await _stream.WriteAsync(new ReadOnlyMemory<byte>(_buffer, 0, compressedBytes), cancellation
 0248                        }
 0249                        Debug.Assert(flushSuccessful == (compressedBytes > 0));
 0250                    } while (flushSuccessful);
 251
 252                    // Always flush on the underlying stream
 0253                    await _stream.FlushAsync(cancellationToken).ConfigureAwait(false);
 0254                }
 255                finally
 0256                {
 0257                    AsyncOperationCompleting();
 0258                }
 0259            }
 0260        }
 261
 262        public override long Seek(long offset, SeekOrigin origin)
 0263        {
 0264            throw new NotSupportedException(SR.NotSupported);
 265        }
 266
 267        public override void SetLength(long value)
 0268        {
 0269            throw new NotSupportedException(SR.NotSupported);
 270        }
 271
 272        public override int ReadByte()
 0273        {
 0274            EnsureDecompressionMode();
 0275            EnsureNotDisposed();
 276
 277            // Try to read a single byte from zlib without allocating an array, pinning an array, etc.
 278            // If zlib doesn't have any data, fall back to the base stream implementation, which will do that.
 279            byte b;
 0280            Debug.Assert(_inflater != null);
 0281            return _inflater.Inflate(out b) ? b : base.ReadByte();
 0282        }
 283
 284        public override int Read(byte[] buffer, int offset, int count)
 0285        {
 0286            ValidateBufferArguments(buffer, offset, count);
 0287            return ReadCore(new Span<byte>(buffer, offset, count));
 0288        }
 289
 290        public override int Read(Span<byte> buffer)
 1302291        {
 1302292            if (GetType() != typeof(DeflateStream))
 0293            {
 294                // DeflateStream is not sealed, and a derived type may have overridden Read(byte[], int, int) prior
 295                // to this Read(Span<byte>) overload being introduced.  In that case, this Read(Span<byte>) overload
 296                // should use the behavior of Read(byte[],int,int) overload.
 0297                return base.Read(buffer);
 298            }
 299            else
 1302300            {
 1302301                return ReadCore(buffer);
 302            }
 1298303        }
 304
 305        internal int ReadCore(Span<byte> buffer)
 1302306        {
 1302307            EnsureDecompressionMode();
 1302308            EnsureNotDisposed();
 1302309            EnsureBufferInitialized();
 1302310            Debug.Assert(_inflater != null);
 311
 312            int bytesRead;
 1956313            while (true)
 1956314            {
 315                // Try to decompress any data from the inflater into the caller's buffer.
 316                // If we're able to decompress any bytes, or if decompression is completed, we're done.
 1956317                bytesRead = _inflater.Inflate(buffer);
 1952318                if (bytesRead != 0 || InflatorIsFinished)
 1297319                {
 1297320                    break;
 321                }
 322
 323                // We were unable to decompress any data.  If the inflater needs additional input
 324                // data to proceed, read some to populate it.
 655325                if (_inflater.NeedsInput())
 655326                {
 655327                    int n = _stream.Read(_buffer, 0, _buffer.Length);
 655328                    if (n <= 0)
 1329                    {
 330                        // - Inflater didn't return any data although a non-empty output buffer was passed by the caller
 331                        // - More input is needed but there is no more input available.
 332                        // - Inflation is not finished yet.
 333                        // - Provided input wasn't completely empty
 334                        // In such case, we are dealing with a truncated input stream.
 1335                        if (s_useStrictValidation && !buffer.IsEmpty && !_inflater.Finished() && _inflater.NonEmptyInput
 0336                        {
 0337                            ThrowTruncatedInvalidData();
 0338                        }
 1339                        break;
 340                    }
 654341                    else if (n > _buffer.Length)
 0342                    {
 0343                        ThrowGenericInvalidData();
 0344                    }
 345                    else
 654346                    {
 654347                        _inflater.SetInput(_buffer, 0, n);
 654348                    }
 654349                }
 350
 654351                if (buffer.IsEmpty)
 0352                {
 353                    // The caller provided a zero-byte buffer.  This is typically done in order to avoid allocating/rent
 354                    // a buffer until data is known to be available.  We don't have perfect knowledge here, as _inflater
 355                    // will return 0 whether or not more data is required, and having input data doesn't necessarily mea
 356                    // decompress into at least one byte of output, but it's a reasonable approximation for the 99% case
 357                    // wrong, it just means that a caller using zero-byte reads as a way to delay getting a buffer to us
 358                    // subsequent call may end up getting one earlier than otherwise preferred.
 0359                    Debug.Assert(bytesRead == 0);
 0360                    break;
 361                }
 654362            }
 363
 364            // When decompression finishes, rewind the stream to the exact end of compressed data
 1298365            if (bytesRead == 0 && InflatorIsFinished && !_decompressionFinished && _stream.CanSeek)
 0366            {
 0367                TryRewindStream(_stream);
 0368                _decompressionFinished = true;
 0369            }
 370
 1298371            return bytesRead;
 1298372        }
 373
 374        private bool InflatorIsFinished =>
 375            // If the stream is finished then we have a few potential cases here:
 376            // 1. DeflateStream => return
 377            // 2. GZipStream that is finished but may have an additional GZipStream appended => feed more input
 378            // 3. GZipStream that is finished and appended with garbage => return
 3899379            _inflater!.Finished() &&
 3899380            (!_inflater.IsGzipStream() || !_inflater.NeedsInput());
 381
 382        private void EnsureNotDisposed()
 4491383        {
 4491384            ObjectDisposedException.ThrowIf(_stream is null, this);
 4491385        }
 386
 387        private void EnsureDecompressionMode()
 2601388        {
 2601389            if (_mode != CompressionMode.Decompress)
 0390                ThrowCannotReadFromDeflateStreamException();
 391
 392            static void ThrowCannotReadFromDeflateStreamException() =>
 0393                throw new InvalidOperationException(SR.CannotReadFromDeflateStream);
 2601394        }
 395
 396        private void EnsureCompressionMode()
 1494397        {
 1494398            if (_mode != CompressionMode.Compress)
 0399                ThrowCannotWriteToDeflateStreamException();
 400
 401            static void ThrowCannotWriteToDeflateStreamException() =>
 0402                throw new InvalidOperationException(SR.CannotWriteToDeflateStream);
 1494403        }
 404
 405        private static void ThrowGenericInvalidData() =>
 406            // The stream is either malicious or poorly implemented and returned a number of
 407            // bytes < 0 || > than the buffer supplied to it.
 0408            throw new InvalidDataException(SR.GenericInvalidData);
 409
 410        private static void ThrowTruncatedInvalidData() =>
 0411            throw new InvalidDataException(SR.TruncatedData);
 412
 413        public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback? asyncCallback, objec
 0414            TaskToAsyncResult.Begin(ReadAsync(buffer, offset, count, CancellationToken.None), asyncCallback, asyncState)
 415
 416        public override int EndRead(IAsyncResult asyncResult)
 0417        {
 0418            EnsureDecompressionMode();
 0419            EnsureNotDisposed();
 0420            return TaskToAsyncResult.End<int>(asyncResult);
 0421        }
 422
 423        public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
 0424        {
 0425            ValidateBufferArguments(buffer, offset, count);
 0426            return ReadAsyncMemory(new Memory<byte>(buffer, offset, count), cancellationToken).AsTask();
 0427        }
 428
 429        public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
 1299430        {
 1299431            if (GetType() != typeof(DeflateStream))
 0432            {
 433                // Ensure that existing streams derived from DeflateStream and that override ReadAsync(byte[],...)
 434                // get their existing behaviors when the newer Memory-based overload is used.
 0435                return base.ReadAsync(buffer, cancellationToken);
 436            }
 437            else
 1299438            {
 1299439                return ReadAsyncMemory(buffer, cancellationToken);
 440            }
 1299441        }
 442
 443        internal ValueTask<int> ReadAsyncMemory(Memory<byte> buffer, CancellationToken cancellationToken)
 1299444        {
 1299445            EnsureDecompressionMode();
 1299446            EnsureNoActiveAsyncOperation();
 1299447            EnsureNotDisposed();
 448
 1299449            if (cancellationToken.IsCancellationRequested)
 0450            {
 0451                return ValueTask.FromCanceled<int>(cancellationToken);
 452            }
 453
 1299454            EnsureBufferInitialized();
 1299455            Debug.Assert(_inflater != null);
 456
 1299457            return Core(buffer, cancellationToken);
 458
 459            async ValueTask<int> Core(Memory<byte> buffer, CancellationToken cancellationToken)
 1299460            {
 1299461                AsyncOperationStarting();
 462                try
 1299463                {
 464                    int bytesRead;
 1950465                    while (true)
 1950466                    {
 467                        // Try to decompress any data from the inflater into the caller's buffer.
 468                        // If we're able to decompress any bytes, or if decompression is completed, we're done.
 1950469                        bytesRead = _inflater.Inflate(buffer.Span);
 1947470                        if (bytesRead != 0 || InflatorIsFinished)
 1296471                        {
 1296472                            break;
 473                        }
 474
 475                        // We were unable to decompress any data.  If the inflater needs additional input
 476                        // data to proceed, read some to populate it.
 651477                        if (_inflater.NeedsInput())
 651478                        {
 651479                            int n = await _stream.ReadAsync(new Memory<byte>(_buffer, 0, _buffer.Length), cancellationTo
 651480                            if (n <= 0)
 0481                            {
 482                                // - Inflater didn't return any data although a non-empty output buffer was passed by th
 483                                // - More input is needed but there is no more input available.
 484                                // - Inflation is not finished yet.
 485                                // - Provided input wasn't completely empty
 486                                // In such case, we are dealing with a truncated input stream.
 0487                                if (s_useStrictValidation && !_inflater.Finished() && _inflater.NonEmptyInput() && !buff
 0488                                {
 0489                                    ThrowTruncatedInvalidData();
 0490                                }
 0491                                break;
 492                            }
 651493                            else if (n > _buffer.Length)
 0494                            {
 0495                                ThrowGenericInvalidData();
 0496                            }
 497                            else
 651498                            {
 651499                                _inflater.SetInput(_buffer, 0, n);
 651500                            }
 651501                        }
 502
 651503                        if (buffer.IsEmpty)
 0504                        {
 505                            // The caller provided a zero-byte buffer.  This is typically done in order to avoid allocat
 506                            // a buffer until data is known to be available.  We don't have perfect knowledge here, as _
 507                            // will return 0 whether or not more data is required, and having input data doesn't necessa
 508                            // decompress into at least one byte of output, but it's a reasonable approximation for the 
 509                            // wrong, it just means that a caller using zero-byte reads as a way to delay getting a buff
 510                            // subsequent call may end up getting one earlier than otherwise preferred.
 0511                            break;
 512                        }
 651513                    }
 514
 515                    // When decompression finishes, rewind the stream to the exact end of compressed data
 1296516                    if (bytesRead == 0 && InflatorIsFinished && !_decompressionFinished && _stream.CanSeek)
 0517                    {
 0518                        TryRewindStream(_stream);
 0519                        _decompressionFinished = true;
 0520                    }
 521
 1296522                    return bytesRead;
 523                }
 524                finally
 1299525                {
 1299526                    AsyncOperationCompleting();
 1299527                }
 1296528            }
 1299529        }
 530
 531        public override void Write(byte[] buffer, int offset, int count)
 0532        {
 0533            ValidateBufferArguments(buffer, offset, count);
 0534            WriteCore(new ReadOnlySpan<byte>(buffer, offset, count));
 0535        }
 536
 537        public override void WriteByte(byte value)
 0538        {
 0539            if (GetType() != typeof(DeflateStream))
 0540            {
 541                // DeflateStream is not sealed, and a derived type may have overridden Write(byte[], int, int) prior
 542                // to this WriteByte override being introduced.  In that case, this WriteByte override
 543                // should use the behavior of the Write(byte[],int,int) overload.
 0544                base.WriteByte(value);
 0545            }
 546            else
 0547            {
 0548                WriteCore(new ReadOnlySpan<byte>(in value));
 0549            }
 0550        }
 551
 552        public override void Write(ReadOnlySpan<byte> buffer)
 747553        {
 747554            if (GetType() != typeof(DeflateStream))
 0555            {
 556                // DeflateStream is not sealed, and a derived type may have overridden Write(byte[], int, int) prior
 557                // to this Write(ReadOnlySpan<byte>) overload being introduced.  In that case, this Write(ReadOnlySpan<b
 558                // should use the behavior of Write(byte[],int,int) overload.
 0559                base.Write(buffer);
 0560            }
 561            else
 747562            {
 747563                WriteCore(buffer);
 747564            }
 747565        }
 566
 567        internal void WriteCore(ReadOnlySpan<byte> buffer)
 747568        {
 747569            EnsureCompressionMode();
 747570            EnsureNotDisposed();
 571
 747572            if (buffer.IsEmpty)
 0573            {
 0574                return;
 575            }
 576
 577            // Write compressed the bytes we already passed to the deflater:
 747578            Debug.Assert(_deflater != null);
 747579            WriteDeflaterOutput();
 580
 581            unsafe
 747582            {
 583                // Pass new bytes through deflater and write them too:
 747584                fixed (byte* bufferPtr = &MemoryMarshal.GetReference(buffer))
 747585                {
 747586                    _deflater.SetInput(bufferPtr, buffer.Length);
 747587                    WriteDeflaterOutput();
 747588                }
 747589            }
 747590        }
 591
 592        private void WriteDeflaterOutput()
 2241593        {
 2241594            Debug.Assert(_deflater != null && _buffer != null);
 2988595            while (!_deflater.NeedsInput())
 747596            {
 747597                int compressedBytes = _deflater.GetDeflateOutput(_buffer);
 747598                if (compressedBytes > 0)
 0599                {
 0600                    _stream.Write(_buffer, 0, compressedBytes);
 0601                }
 747602            }
 2241603        }
 604
 605        // This is called by Flush:
 606        private void FlushBuffers()
 0607        {
 608            // Compress any bytes left:
 0609            WriteDeflaterOutput();
 610
 0611            Debug.Assert(_deflater != null && _buffer != null);
 612            // Pull out any bytes left inside deflater:
 613            bool flushSuccessful;
 614            do
 0615            {
 616                int compressedBytes;
 0617                flushSuccessful = _deflater.Flush(_buffer, out compressedBytes);
 0618                if (flushSuccessful)
 0619                {
 0620                    _stream.Write(_buffer, 0, compressedBytes);
 0621                }
 0622                Debug.Assert(flushSuccessful == (compressedBytes > 0));
 0623            } while (flushSuccessful);
 624
 625            // Always flush on the underlying stream
 0626            _stream.Flush();
 0627        }
 628
 629        // This is called by Dispose:
 630        private void PurgeBuffers(bool disposing)
 1500631        {
 1500632            if (!disposing)
 0633                return;
 634
 1500635            if (_stream == null)
 0636                return;
 637
 1500638            if (_mode != CompressionMode.Compress)
 753639                return;
 640
 747641            Debug.Assert(_deflater != null && _buffer != null);
 642            // Compress any bytes left
 747643            WriteDeflaterOutput();
 644
 645            // Pull out any bytes left inside deflater:
 646            bool finished;
 647            do
 747648            {
 649                int compressedBytes;
 747650                finished = _deflater.Finish(_buffer, out compressedBytes);
 651
 747652                if (compressedBytes > 0)
 747653                    _stream.Write(_buffer, 0, compressedBytes);
 1494654            } while (!finished);
 1500655        }
 656
 657        private async ValueTask PurgeBuffersAsync()
 1497658        {
 659            // Same logic as PurgeBuffers, except with async counterparts.
 660
 1497661            if (_stream == null)
 0662                return;
 663
 1497664            if (_mode != CompressionMode.Compress)
 750665                return;
 666
 747667            Debug.Assert(_deflater != null && _buffer != null);
 668            // Compress any bytes left
 747669            await WriteDeflaterOutputAsync(default).ConfigureAwait(false);
 670
 671            // Pull out any bytes left inside deflater:
 672            bool finished;
 673            do
 747674            {
 675                int compressedBytes;
 747676                finished = _deflater.Finish(_buffer, out compressedBytes);
 677
 747678                if (compressedBytes > 0)
 747679                    await _stream.WriteAsync(new ReadOnlyMemory<byte>(_buffer, 0, compressedBytes)).ConfigureAwait(false
 1494680            } while (!finished);
 1497681        }
 682
 683        /// <summary>
 684        /// Rewinds the underlying stream to the exact end of the compressed data if there are unconsumed bytes.
 685        /// This is called when decompression finishes to reset the stream position.
 686        /// </summary>
 687        private void TryRewindStream(Stream stream)
 0688        {
 0689            Debug.Assert(stream != null);
 0690            Debug.Assert(_mode == CompressionMode.Decompress);
 0691            Debug.Assert(stream.CanSeek);
 0692            Debug.Assert(_inflater != null);
 693
 694            // Check if there are unconsumed bytes in the inflater's input buffer
 0695            int unconsumedBytes = _inflater.GetAvailableInput();
 0696            if (unconsumedBytes > 0)
 0697            {
 698                try
 0699                {
 700                    // Rewind the stream to the exact end of the compressed data
 0701                    stream.Seek(-unconsumedBytes, SeekOrigin.Current);
 0702                }
 0703                catch
 0704                {
 705                    // If seeking fails, we don't want to throw during disposal
 0706                }
 0707            }
 0708        }
 709
 710        protected override void Dispose(bool disposing)
 1500711        {
 712            try
 1500713            {
 1500714                PurgeBuffers(disposing);
 1500715            }
 716            finally
 1500717            {
 718                // Close the underlying stream even if PurgeBuffers threw.
 719                // Stream.Close() may throw here (may or may not be due to the same error).
 720                // In this case, we still need to clean up internal resources, hence the inner finally blocks.
 721                try
 1500722                {
 1500723                    if (disposing && !_leaveOpen)
 852724                    {
 852725                        _stream?.Dispose();
 852726                    }
 1500727                }
 728                finally
 1500729                {
 1500730                    _stream = null!;
 731
 732                    try
 1500733                    {
 1500734                        _deflater?.Dispose();
 1500735                        _inflater?.Dispose();
 1500736                    }
 737                    finally
 1500738                    {
 1500739                        _deflater = null;
 1500740                        _inflater = null;
 741
 1500742                        byte[]? buffer = _buffer;
 1500743                        if (buffer != null)
 1401744                        {
 1401745                            _buffer = null;
 1401746                            if (!_activeAsyncOperation)
 1401747                            {
 1401748                                ArrayPool<byte>.Shared.Return(buffer);
 1401749                            }
 1401750                        }
 751
 1500752                        base.Dispose(disposing);
 1500753                    }
 1500754                }
 1500755            }
 1500756        }
 757
 758        public override ValueTask DisposeAsync()
 1497759        {
 1497760            return GetType() == typeof(DeflateStream) ?
 1497761                Core() :
 1497762                base.DisposeAsync();
 763
 764            async ValueTask Core()
 1497765            {
 766                // Same logic as Dispose(true), except with async counterparts.
 767                try
 1497768                {
 1497769                    await PurgeBuffersAsync().ConfigureAwait(false);
 1497770                }
 771                finally
 1497772                {
 773                    // Close the underlying stream even if PurgeBuffers threw.
 774                    // Stream.Close() may throw here (may or may not be due to the same error).
 775                    // In this case, we still need to clean up internal resources, hence the inner finally blocks.
 1497776                    Stream stream = _stream;
 1497777                    _stream = null!;
 778                    try
 1497779                    {
 1497780                        if (!_leaveOpen && stream != null)
 849781                        {
 849782                            await stream.DisposeAsync().ConfigureAwait(false);
 849783                        }
 1497784                    }
 785                    finally
 1497786                    {
 787                        try
 1497788                        {
 1497789                            _deflater?.Dispose();
 1497790                            _inflater?.Dispose();
 1497791                        }
 792                        finally
 1497793                        {
 1497794                            _deflater = null;
 1497795                            _inflater = null;
 796
 1497797                            byte[]? buffer = _buffer;
 1497798                            if (buffer != null)
 1398799                            {
 1398800                                _buffer = null;
 1398801                                if (!_activeAsyncOperation)
 1398802                                {
 1398803                                    ArrayPool<byte>.Shared.Return(buffer);
 1398804                                }
 1398805                            }
 1497806                        }
 1497807                    }
 1497808                }
 809            }
 2994810        }
 811
 812        public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback? asyncCallback, obje
 0813            TaskToAsyncResult.Begin(WriteAsync(buffer, offset, count, CancellationToken.None), asyncCallback, asyncState
 814
 815        public override void EndWrite(IAsyncResult asyncResult)
 0816        {
 0817            EnsureCompressionMode();
 0818            EnsureNotDisposed();
 0819            TaskToAsyncResult.End(asyncResult);
 0820        }
 821
 822        public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
 0823        {
 0824            ValidateBufferArguments(buffer, offset, count);
 0825            return WriteAsyncMemory(new ReadOnlyMemory<byte>(buffer, offset, count), cancellationToken).AsTask();
 0826        }
 827
 828        public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
 747829        {
 747830            if (GetType() != typeof(DeflateStream))
 0831            {
 832                // Ensure that existing streams derived from DeflateStream and that override WriteAsync(byte[],...)
 833                // get their existing behaviors when the newer Memory-based overload is used.
 0834                return base.WriteAsync(buffer, cancellationToken);
 835            }
 836            else
 747837            {
 747838                return WriteAsyncMemory(buffer, cancellationToken);
 839            }
 747840        }
 841
 842        internal ValueTask WriteAsyncMemory(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken)
 747843        {
 747844            EnsureCompressionMode();
 747845            EnsureNoActiveAsyncOperation();
 747846            EnsureNotDisposed();
 847
 747848            return
 747849                cancellationToken.IsCancellationRequested ? ValueTask.FromCanceled(cancellationToken) :
 747850                buffer.IsEmpty ? default :
 747851                Core(buffer, cancellationToken);
 852
 853            async ValueTask Core(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken)
 747854            {
 747855                AsyncOperationStarting();
 856                try
 747857                {
 747858                    await WriteDeflaterOutputAsync(cancellationToken).ConfigureAwait(false);
 859
 860                    // Pass new bytes through deflater
 747861                    Debug.Assert(_deflater != null);
 747862                    _deflater.SetInput(buffer);
 863
 747864                    await WriteDeflaterOutputAsync(cancellationToken).ConfigureAwait(false);
 747865                }
 866                finally
 747867                {
 747868                    AsyncOperationCompleting();
 747869                }
 747870            }
 747871        }
 872
 873        /// <summary>
 874        /// Writes the bytes that have already been deflated
 875        /// </summary>
 876        private async ValueTask WriteDeflaterOutputAsync(CancellationToken cancellationToken)
 2241877        {
 2241878            Debug.Assert(_deflater != null && _buffer != null);
 2988879            while (!_deflater.NeedsInput())
 747880            {
 747881                int compressedBytes = _deflater.GetDeflateOutput(_buffer);
 747882                if (compressedBytes > 0)
 0883                {
 0884                    await _stream.WriteAsync(new ReadOnlyMemory<byte>(_buffer, 0, compressedBytes), cancellationToken).C
 0885                }
 747886            }
 2241887        }
 888
 889        public override void CopyTo(Stream destination, int bufferSize)
 99890        {
 99891            ValidateCopyToArguments(destination, bufferSize);
 892
 99893            EnsureNotDisposed();
 99894            if (!CanRead) throw new NotSupportedException();
 895
 99896            new CopyToStream(this, destination, bufferSize).CopyFromSourceToDestination();
 99897        }
 898
 899        public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
 99900        {
 99901            ValidateCopyToArguments(destination, bufferSize);
 902
 99903            EnsureNotDisposed();
 99904            if (!CanRead) throw new NotSupportedException();
 99905            EnsureNoActiveAsyncOperation();
 906
 907            // Early check for cancellation
 99908            if (cancellationToken.IsCancellationRequested)
 0909            {
 0910                return Task.FromCanceled<int>(cancellationToken);
 911            }
 912
 913            // Do the copy
 99914            return new CopyToStream(this, destination, bufferSize, cancellationToken).CopyFromSourceToDestinationAsync()
 99915        }
 916
 917        private sealed class CopyToStream : Stream
 918        {
 919            private readonly DeflateStream _deflateStream;
 920            private readonly Stream _destination;
 921            private readonly CancellationToken _cancellationToken;
 922            private byte[] _arrayPoolBuffer;
 923
 924            public CopyToStream(DeflateStream deflateStream, Stream destination, int bufferSize) :
 99925                this(deflateStream, destination, bufferSize, CancellationToken.None)
 99926            {
 99927            }
 928
 198929            public CopyToStream(DeflateStream deflateStream, Stream destination, int bufferSize, CancellationToken cance
 198930            {
 198931                Debug.Assert(deflateStream != null);
 198932                Debug.Assert(destination != null);
 198933                Debug.Assert(bufferSize > 0);
 934
 198935                _deflateStream = deflateStream;
 198936                _destination = destination;
 198937                _cancellationToken = cancellationToken;
 198938                _arrayPoolBuffer = ArrayPool<byte>.Shared.Rent(bufferSize);
 198939            }
 940
 941            public async Task CopyFromSourceToDestinationAsync()
 99942            {
 99943                _deflateStream.AsyncOperationStarting();
 944                try
 99945                {
 99946                    Debug.Assert(_deflateStream._inflater != null);
 947                    // Flush any existing data in the inflater to the destination stream.
 99948                    while (!_deflateStream._inflater.Finished())
 99949                    {
 99950                        int bytesRead = _deflateStream._inflater.Inflate(_arrayPoolBuffer, 0, _arrayPoolBuffer.Length);
 99951                        if (bytesRead > 0)
 0952                        {
 0953                            await _destination.WriteAsync(new ReadOnlyMemory<byte>(_arrayPoolBuffer, 0, bytesRead), _can
 0954                        }
 99955                        else if (_deflateStream._inflater.NeedsInput())
 99956                        {
 957                            // only break if we read 0 and ran out of input, if input is still available it may be anoth
 99958                            break;
 959                        }
 0960                    }
 961
 962                    // Now, use the source stream's CopyToAsync to push directly to our inflater via this helper stream
 99963                    await _deflateStream._stream.CopyToAsync(this, _arrayPoolBuffer.Length, _cancellationToken).Configur
 99964                    if (s_useStrictValidation && !_deflateStream._inflater.Finished())
 0965                    {
 0966                        ThrowTruncatedInvalidData();
 0967                    }
 968
 969                    // Rewind the stream if decompression has finished and the stream supports seeking
 99970                    if (_deflateStream._inflater.Finished() && !_deflateStream._decompressionFinished && _deflateStream.
 0971                    {
 0972                        _deflateStream.TryRewindStream(_deflateStream._stream);
 0973                        _deflateStream._decompressionFinished = true;
 0974                    }
 99975                }
 976                finally
 99977                {
 99978                    _deflateStream.AsyncOperationCompleting();
 979
 99980                    ArrayPool<byte>.Shared.Return(_arrayPoolBuffer);
 99981                    _arrayPoolBuffer = null!;
 99982                }
 99983            }
 984
 985            public void CopyFromSourceToDestination()
 99986            {
 987                try
 99988                {
 99989                    Debug.Assert(_deflateStream._inflater != null);
 990                    // Flush any existing data in the inflater to the destination stream.
 99991                    while (!_deflateStream._inflater.Finished())
 99992                    {
 99993                        int bytesRead = _deflateStream._inflater.Inflate(_arrayPoolBuffer, 0, _arrayPoolBuffer.Length);
 99994                        if (bytesRead > 0)
 0995                        {
 0996                            _destination.Write(_arrayPoolBuffer, 0, bytesRead);
 0997                        }
 99998                        else if (_deflateStream._inflater.NeedsInput())
 99999                        {
 1000                            // only break if we read 0 and ran out of input, if input is still available it may be anoth
 991001                            break;
 1002                        }
 01003                    }
 1004
 1005                    // Now, use the source stream's CopyToAsync to push directly to our inflater via this helper stream
 991006                    _deflateStream._stream.CopyTo(this, _arrayPoolBuffer.Length);
 991007                    if (s_useStrictValidation && !_deflateStream._inflater.Finished())
 01008                    {
 01009                        ThrowTruncatedInvalidData();
 01010                    }
 1011
 1012                    // Rewind the stream if decompression has finished and the stream supports seeking
 991013                    if (_deflateStream._inflater.Finished() && !_deflateStream._decompressionFinished && _deflateStream.
 01014                    {
 01015                        _deflateStream.TryRewindStream(_deflateStream._stream);
 01016                        _deflateStream._decompressionFinished = true;
 01017                    }
 991018                }
 1019                finally
 991020                {
 991021                    ArrayPool<byte>.Shared.Return(_arrayPoolBuffer);
 991022                    _arrayPoolBuffer = null!;
 991023                }
 991024            }
 1025
 1026            public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
 01027            {
 01028                Debug.Assert(buffer != _arrayPoolBuffer);
 01029                _deflateStream.EnsureNotDisposed();
 01030                if (count <= 0)
 01031                {
 01032                    return Task.CompletedTask;
 1033                }
 01034                else if (count > buffer.Length - offset)
 01035                {
 1036                    // The buffer stream is either malicious or poorly implemented and returned a number of
 1037                    // bytes larger than the buffer supplied to it.
 01038                    return Task.FromException(new InvalidDataException(SR.GenericInvalidData));
 1039                }
 1040
 01041                return WriteAsyncCore(buffer.AsMemory(offset, count), cancellationToken).AsTask();
 01042            }
 1043
 1044            public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = defa
 991045            {
 991046                _deflateStream.EnsureNotDisposed();
 1047
 991048                return WriteAsyncCore(buffer, cancellationToken);
 991049            }
 1050
 1051            private async ValueTask WriteAsyncCore(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken)
 991052            {
 991053                Debug.Assert(_deflateStream._inflater is not null);
 1054
 1055                // Feed the data from base stream into decompression engine.
 991056                _deflateStream._inflater.SetInput(buffer);
 1057
 1058                // While there's more decompressed data available, forward it to the buffer stream.
 1981059                while (!_deflateStream._inflater.Finished())
 991060                {
 991061                    int bytesRead = _deflateStream._inflater.Inflate(new Span<byte>(_arrayPoolBuffer));
 991062                    if (bytesRead > 0)
 991063                    {
 991064                        await _destination.WriteAsync(new ReadOnlyMemory<byte>(_arrayPoolBuffer, 0, bytesRead), cancella
 991065                    }
 01066                    else if (_deflateStream._inflater.NeedsInput())
 01067                    {
 1068                        // only break if we read 0 and ran out of input, if input is still available it may be another G
 01069                        break;
 1070                    }
 991071                }
 991072            }
 1073
 1074            public override void Write(byte[] buffer, int offset, int count)
 991075            {
 991076                Debug.Assert(buffer != _arrayPoolBuffer);
 991077                _deflateStream.EnsureNotDisposed();
 1078
 991079                if (count <= 0)
 01080                {
 01081                    return;
 1082                }
 991083                else if (count > buffer.Length - offset)
 01084                {
 1085                    // The buffer stream is either malicious or poorly implemented and returned a number of
 1086                    // bytes larger than the buffer supplied to it.
 01087                    throw new InvalidDataException(SR.GenericInvalidData);
 1088                }
 1089
 991090                Debug.Assert(_deflateStream._inflater != null);
 1091                // Feed the data from base stream into the decompression engine.
 991092                _deflateStream._inflater.SetInput(buffer, offset, count);
 1093
 1094                // While there's more decompressed data available, forward it to the buffer stream.
 1981095                while (!_deflateStream._inflater.Finished())
 991096                {
 991097                    int bytesRead = _deflateStream._inflater.Inflate(new Span<byte>(_arrayPoolBuffer));
 991098                    if (bytesRead > 0)
 991099                    {
 991100                        _destination.Write(_arrayPoolBuffer, 0, bytesRead);
 991101                    }
 01102                    else if (_deflateStream._inflater.NeedsInput())
 01103                    {
 1104                        // only break if we read 0 and ran out of input, if input is still available it may be another G
 01105                        break;
 1106                    }
 991107                }
 991108            }
 1109
 1981110            public override bool CanWrite => true;
 01111            public override void Flush() { }
 01112            public override bool CanRead => false;
 01113            public override bool CanSeek => false;
 01114            public override long Length { get { throw new NotSupportedException(); } }
 01115            public override long Position { get { throw new NotSupportedException(); } set { throw new NotSupportedExcep
 01116            public override int Read(byte[] buffer, int offset, int count) { throw new NotSupportedException(); }
 01117            public override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); }
 01118            public override void SetLength(long value) { throw new NotSupportedException(); }
 1119        }
 1120
 1121        private void EnsureNoActiveAsyncOperation()
 21451122        {
 21451123            if (_activeAsyncOperation)
 01124            {
 01125                ThrowInvalidBeginCall();
 01126            }
 21451127        }
 1128
 1129        private void AsyncOperationStarting()
 21451130        {
 21451131            if (Interlocked.Exchange(ref _activeAsyncOperation, true))
 01132            {
 01133                ThrowInvalidBeginCall();
 01134            }
 21451135        }
 1136
 1137        private void AsyncOperationCompleting()
 21451138        {
 21451139            Debug.Assert(_activeAsyncOperation);
 21451140            _activeAsyncOperation = false;
 21451141        }
 1142
 1143        private static void ThrowInvalidBeginCall() =>
 01144            throw new InvalidOperationException(SR.InvalidBeginCall);
 1145
 11146        private static readonly bool s_useStrictValidation =
 11147            AppContext.TryGetSwitch("System.IO.Compression.UseStrictValidation", out bool strictValidation) ? strictVali
 1148    }
 1149}

Methods/Properties

.ctor(System.IO.Stream,System.IO.Compression.CompressionMode,System.Int64)
.ctor(System.IO.Stream,System.IO.Compression.CompressionMode)
.ctor(System.IO.Stream,System.IO.Compression.CompressionMode,System.Boolean)
.ctor(System.IO.Stream,System.IO.Compression.CompressionLevel)
.ctor(System.IO.Stream,System.IO.Compression.CompressionLevel,System.Boolean)
.ctor(System.IO.Stream,System.IO.Compression.ZLibCompressionOptions,System.Boolean)
.ctor(System.IO.Stream,System.IO.Compression.ZLibCompressionOptions,System.Boolean,System.Int32)
.ctor(System.IO.Stream,System.IO.Compression.CompressionMode,System.Boolean,System.Int32,System.Int64)
.ctor(System.IO.Stream,System.IO.Compression.CompressionLevel,System.Boolean,System.Int32)
InitializeDeflater(System.IO.Stream,System.IO.Compression.ZLibNative/CompressionLevel,System.IO.Compression.ZLibNative/CompressionStrategy,System.Boolean,System.Int32)
GetZLibNativeCompressionLevel(System.IO.Compression.CompressionLevel)
GetMemLevel(System.IO.Compression.ZLibNative/CompressionLevel)
InitializeBuffer()
EnsureBufferInitialized()
BaseStream()
CanRead()
CanWrite()
CanSeek()
Length()
Position()
Position(System.Int64)
Flush()
FlushAsync(System.Threading.CancellationToken)
Core(System.Threading.CancellationToken)
Seek(System.Int64,System.IO.SeekOrigin)
SetLength(System.Int64)
ReadByte()
Read(System.Byte[],System.Int32,System.Int32)
Read(System.Span`1<System.Byte>)
ReadCore(System.Span`1<System.Byte>)
InflatorIsFinished()
EnsureNotDisposed()
EnsureDecompressionMode()
ThrowCannotReadFromDeflateStreamException()
EnsureCompressionMode()
ThrowCannotWriteToDeflateStreamException()
ThrowGenericInvalidData()
ThrowTruncatedInvalidData()
BeginRead(System.Byte[],System.Int32,System.Int32,System.AsyncCallback,System.Object)
EndRead(System.IAsyncResult)
ReadAsync(System.Byte[],System.Int32,System.Int32,System.Threading.CancellationToken)
ReadAsync(System.Memory`1<System.Byte>,System.Threading.CancellationToken)
ReadAsyncMemory(System.Memory`1<System.Byte>,System.Threading.CancellationToken)
Core(System.Memory`1<System.Byte>,System.Threading.CancellationToken)
Write(System.Byte[],System.Int32,System.Int32)
WriteByte(System.Byte)
Write(System.ReadOnlySpan`1<System.Byte>)
WriteCore(System.ReadOnlySpan`1<System.Byte>)
WriteDeflaterOutput()
FlushBuffers()
PurgeBuffers(System.Boolean)
PurgeBuffersAsync()
TryRewindStream(System.IO.Stream)
Dispose(System.Boolean)
DisposeAsync()
Core()
BeginWrite(System.Byte[],System.Int32,System.Int32,System.AsyncCallback,System.Object)
EndWrite(System.IAsyncResult)
WriteAsync(System.Byte[],System.Int32,System.Int32,System.Threading.CancellationToken)
WriteAsync(System.ReadOnlyMemory`1<System.Byte>,System.Threading.CancellationToken)
WriteAsyncMemory(System.ReadOnlyMemory`1<System.Byte>,System.Threading.CancellationToken)
Core(System.ReadOnlyMemory`1<System.Byte>,System.Threading.CancellationToken)
WriteDeflaterOutputAsync(System.Threading.CancellationToken)
CopyTo(System.IO.Stream,System.Int32)
CopyToAsync(System.IO.Stream,System.Int32,System.Threading.CancellationToken)
.ctor(System.IO.Compression.DeflateStream,System.IO.Stream,System.Int32)
.ctor(System.IO.Compression.DeflateStream,System.IO.Stream,System.Int32,System.Threading.CancellationToken)
CopyFromSourceToDestinationAsync()
CopyFromSourceToDestination()
WriteAsync(System.Byte[],System.Int32,System.Int32,System.Threading.CancellationToken)
WriteAsync(System.ReadOnlyMemory`1<System.Byte>,System.Threading.CancellationToken)
WriteAsyncCore(System.ReadOnlyMemory`1<System.Byte>,System.Threading.CancellationToken)
Write(System.Byte[],System.Int32,System.Int32)
CanWrite()
Flush()
CanRead()
CanSeek()
Length()
Position()
Read(System.Byte[],System.Int32,System.Int32)
Seek(System.Int64,System.IO.SeekOrigin)
SetLength(System.Int64)
EnsureNoActiveAsyncOperation()
AsyncOperationStarting()
AsyncOperationCompleting()
ThrowInvalidBeginCall()
.cctor()