< Summary

Information
Class: System.IO.Compression.DeflateDecoder
Assembly: System.IO.Compression
File(s): D:\runner\runtime\src\libraries\System.IO.Compression\src\System\IO\Compression\DeflateDecoder.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 68
Coverable lines: 68
Total lines: 149
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 22
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor()100%110%
.ctor(...)100%110%
Dispose()0%220%
EnsureNotDisposed()100%110%
Decompress(...)0%16160%
Reset()100%110%
TryDecompress(...)0%440%

File(s)

D:\runner\runtime\src\libraries\System.IO.Compression\src\System\IO\Compression\DeflateDecoder.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.Runtime.InteropServices;
 7
 8namespace System.IO.Compression
 9{
 10    /// <summary>
 11    /// Provides methods and static methods to decode data compressed in the Deflate data format in a streamless, non-al
 12    /// </summary>
 13    public sealed class DeflateDecoder : IDisposable
 14    {
 15        private ZLibNative.ZLibStreamHandle? _state;
 16        private readonly int _windowBits;
 17        private bool _disposed;
 18        private bool _finished;
 19
 20        /// <summary>
 21        /// Initializes a new instance of the <see cref="DeflateDecoder"/> class.
 22        /// </summary>
 23        /// <exception cref="IOException">Failed to create the <see cref="DeflateDecoder"/> instance.</exception>
 24        public DeflateDecoder()
 025            : this(ZLibNative.Deflate_DefaultWindowBits)
 026        {
 027        }
 28
 029        internal DeflateDecoder(int windowBits)
 030        {
 031            _windowBits = windowBits;
 032            _state = ZLibNative.ZLibStreamHandle.CreateForInflate(windowBits);
 033        }
 34
 35        /// <summary>
 36        /// Frees and disposes unmanaged resources.
 37        /// </summary>
 38        public void Dispose()
 039        {
 040            _disposed = true;
 041            _state?.Dispose();
 042            _state = null;
 043        }
 44
 45        private void EnsureNotDisposed()
 046        {
 047            ObjectDisposedException.ThrowIf(_disposed, this);
 048        }
 49
 50        /// <summary>
 51        /// Decompresses a read-only byte span into a destination span.
 52        /// </summary>
 53        /// <param name="source">A read-only span of bytes containing the compressed source data.</param>
 54        /// <param name="destination">When this method returns, a byte span where the decompressed data is stored.</para
 55        /// <param name="bytesConsumed">When this method returns, the total number of bytes that were read from <paramre
 56        /// <param name="bytesWritten">When this method returns, the total number of bytes that were written to <paramre
 57        /// <returns>One of the enumeration values that describes the status with which the span-based operation finishe
 58        /// <exception cref="ObjectDisposedException">The decoder has been disposed.</exception>
 59        public OperationStatus Decompress(ReadOnlySpan<byte> source, Span<byte> destination, out int bytesConsumed, out 
 060        {
 061            EnsureNotDisposed();
 062            Debug.Assert(_state is not null);
 63
 064            bytesConsumed = 0;
 065            bytesWritten = 0;
 66
 067            if (_finished)
 068            {
 069                return OperationStatus.Done;
 70            }
 71
 072            if (destination.IsEmpty && source.Length > 0)
 073            {
 074                return OperationStatus.DestinationTooSmall;
 75            }
 76
 77            unsafe
 078            {
 079                fixed (byte* inputPtr = &MemoryMarshal.GetReference(source))
 080                fixed (byte* outputPtr = &MemoryMarshal.GetReference(destination))
 081                {
 082                    _state.NextIn = (IntPtr)inputPtr;
 083                    _state.AvailIn = (uint)source.Length;
 084                    _state.NextOut = (IntPtr)outputPtr;
 085                    _state.AvailOut = (uint)destination.Length;
 86
 087                    ZLibNative.ErrorCode errorCode = _state.Inflate(ZLibNative.FlushCode.NoFlush);
 88
 089                    bytesConsumed = source.Length - (int)_state.AvailIn;
 090                    bytesWritten = destination.Length - (int)_state.AvailOut;
 91
 092                    OperationStatus status = errorCode switch
 093                    {
 094                        ZLibNative.ErrorCode.Ok or ZLibNative.ErrorCode.BufError => _state.AvailOut == 0
 095                            ? OperationStatus.DestinationTooSmall
 096                            : OperationStatus.NeedMoreData,
 097                        ZLibNative.ErrorCode.StreamEnd => OperationStatus.Done,
 098                        _ => OperationStatus.InvalidData
 099                    };
 100
 101                    // Track if decompression is finished
 0102                    if (errorCode == ZLibNative.ErrorCode.StreamEnd)
 0103                    {
 0104                        _finished = true;
 0105                    }
 106
 0107                    return status;
 108                }
 109            }
 0110        }
 111
 112        /// <summary>
 113        /// Resets the decoder to its initial state so the same instance can be reused for a new, independent decompress
 114        /// </summary>
 115        /// <remarks>
 116        /// After this method returns, any sliding-window history from a previous decompression is discarded.
 117        /// </remarks>
 118        /// <exception cref="ObjectDisposedException">The decoder has been disposed.</exception>
 119        public void Reset()
 0120        {
 0121            EnsureNotDisposed();
 0122            Debug.Assert(_state is not null);
 123
 0124            _state.InflateReset2_(_windowBits);
 0125            _finished = false;
 0126        }
 127
 128        /// <summary>
 129        /// Tries to decompress a source byte span into a destination span.
 130        /// </summary>
 131        /// <param name="source">A read-only span of bytes containing the compressed source data.</param>
 132        /// <param name="destination">When this method returns, a span of bytes where the decompressed data is stored.</
 133        /// <param name="bytesWritten">When this method returns, the total number of bytes that were written to <paramre
 134        /// <returns><see langword="true"/> if the decompression operation was successful; <see langword="false"/> other
 135        public static bool TryDecompress(ReadOnlySpan<byte> source, Span<byte> destination, out int bytesWritten)
 0136        {
 0137            using var decoder = new DeflateDecoder();
 0138            OperationStatus status = decoder.Decompress(source, destination, out int consumed, out bytesWritten);
 139
 0140            bool success = status == OperationStatus.Done && consumed == source.Length;
 0141            if (!success)
 0142            {
 0143                bytesWritten = 0;
 0144            }
 145
 0146            return success;
 0147        }
 148    }
 149}