File: System\IO\Compression\GZipDecoder.cs
Web Access
Project: src\src\libraries\System.IO.Compression\src\System.IO.Compression.csproj (System.IO.Compression)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Buffers;
 
namespace System.IO.Compression
{
    /// <summary>
    /// Provides methods and static methods to decode data compressed in the GZip data format in a streamless, non-allocating, and performant manner.
    /// </summary>
    public sealed class GZipDecoder : IDisposable
    {
        private readonly DeflateDecoder _deflateDecoder;
        private bool _disposed;
 
        /// <summary>
        /// Initializes a new instance of the <see cref="GZipDecoder"/> class.
        /// </summary>
        /// <exception cref="IOException">Failed to create the <see cref="GZipDecoder"/> instance.</exception>
        public GZipDecoder()
        {
            _deflateDecoder = new DeflateDecoder(ZLibNative.GZip_DefaultWindowBits);
        }
 
        /// <summary>
        /// Frees and disposes unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            _disposed = true;
            _deflateDecoder.Dispose();
        }
 
        private void EnsureNotDisposed()
        {
            ObjectDisposedException.ThrowIf(_disposed, this);
        }
 
        /// <summary>
        /// Decompresses a read-only byte span into a destination span.
        /// </summary>
        /// <param name="source">A read-only span of bytes containing the compressed source data.</param>
        /// <param name="destination">When this method returns, a byte span where the decompressed data is stored.</param>
        /// <param name="bytesConsumed">When this method returns, the total number of bytes that were read from <paramref name="source"/>.</param>
        /// <param name="bytesWritten">When this method returns, the total number of bytes that were written to <paramref name="destination"/>.</param>
        /// <returns>One of the enumeration values that describes the status with which the span-based operation finished.</returns>
        public OperationStatus Decompress(ReadOnlySpan<byte> source, Span<byte> destination, out int bytesConsumed, out int bytesWritten)
        {
            EnsureNotDisposed();
            return _deflateDecoder.Decompress(source, destination, out bytesConsumed, out bytesWritten);
        }
 
        /// <summary>
        /// Tries to decompress a source byte span into a destination span.
        /// </summary>
        /// <param name="source">A read-only span of bytes containing the compressed source data.</param>
        /// <param name="destination">When this method returns, a span of bytes where the decompressed data is stored.</param>
        /// <param name="bytesWritten">When this method returns, the total number of bytes that were written to <paramref name="destination"/>.</param>
        /// <returns><see langword="true"/> if the decompression operation was successful; <see langword="false"/> otherwise.</returns>
        public static bool TryDecompress(ReadOnlySpan<byte> source, Span<byte> destination, out int bytesWritten)
        {
            using var decoder = new GZipDecoder();
            OperationStatus status = decoder.Decompress(source, destination, out int consumed, out bytesWritten);
 
            bool success = status == OperationStatus.Done && consumed == source.Length;
            if (!success)
            {
                bytesWritten = 0;
            }
 
            return success;
        }
    }
}