internal ZlibException(ZResult result, bool compress, byte[] input, byte[] output)
     : base(ResultMessage(result, compress))
 {
     Result       = result;
     InputBuffer  = input;
     OutputBuffer = output;
 }
        /// <summary>
        ///  Gets the decompressed length of the compressed data and length.
        /// </summary>
        /// <param name="compressed">The compressed data.</param>
        /// <param name="compressedLength">The actual length of the compressed data.</param>
        /// <returns>The length of the compressed data.</returns>
        ///
        /// <exception cref="ArgumentNullException">
        ///  <paramref name="compressed"/> is null.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        ///  <paramref name="compressedLength"/> is less than zero.
        /// </exception>
        /// <exception cref="ZlibException">
        ///  A Zlib error occurred, or the resulting length was greater than <see cref="int.MaxValue"/>.
        /// </exception>
        public static int DecompressedLength(byte[] compressed, int compressedLength)
        {
            if (compressed == null)
            {
                throw new ArgumentNullException(nameof(compressed));
            }
            if (compressedLength < 0)
            {
                throw ArgumentOutOfRangeUtils.OutsideMin(nameof(compressedLength), compressedLength, 0, true);
            }

            int     decompressedLength = 0;
            ZResult result             = UncompressNative(new byte[0], ref decompressedLength, compressed, compressedLength);

            if (result != ZResult.OK && result != ZResult.BufferError)
            {
                throw new ZlibException(result, false, compressed, new byte[0]);
            }

            if (decompressedLength < 0)
            {
                throw new ZlibException($"Decompressed length of {nameof(compressedLength)} is greater " +
                                        $"than {nameof(Int32)}.{nameof(int.MaxValue)}!");
            }
            return(decompressedLength);
        }
        /// <summary>
        ///  Decompresses the compressed data and length to the output decompression buffer and length.
        /// </summary>
        /// <param name="decompressed">The decompression buffer.</param>
        /// <param name="decompressedLength">The actual length of the decompression buffer.</param>
        /// <param name="compressed">The compressed data.</param>
        /// <param name="compressedLength">The actual length of the compressed data.</param>
        ///
        /// <exception cref="ArgumentNullException">
        ///  <paramref name="decompressed"/> or <paramref name="compressed"/> is null.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        ///  <paramref name="decompressedLength"/> or <paramref name="compressedLength"/> is less than zero.
        /// </exception>
        /// <exception cref="ZlibException">
        ///  A Zlib error occurred, or the resulting length was greater than <see cref="int.MaxValue"/>.
        /// </exception>
        public static void Decompress(byte[] decompressed, ref int decompressedLength, byte[] compressed,
                                      int compressedLength)
        {
            if (decompressed == null)
            {
                throw new ArgumentNullException(nameof(decompressed));
            }
            if (compressed == null)
            {
                throw new ArgumentNullException(nameof(compressed));
            }
            if (decompressedLength < 0)
            {
                throw ArgumentOutOfRangeUtils.OutsideMin(nameof(decompressedLength), decompressedLength, 0, true);
            }
            if (compressedLength < 0)
            {
                throw ArgumentOutOfRangeUtils.OutsideMin(nameof(compressedLength), compressedLength, 0, true);
            }

            ZResult result = UncompressNative(decompressed, ref decompressedLength, compressed, compressedLength);

            if (result != ZResult.OK)
            {
                throw new ZlibException(result, false, compressed, decompressed);
            }
        }
        /// <summary>
        ///  Gets the compressed length of the decompressed data and length.
        /// </summary>
        /// <param name="decompressed">The decompressed data.</param>
        /// <param name="decompressedLength">The actual length of the decompressed data.</param>
        /// <returns>The length of the compressed data.</returns>
        ///
        /// <exception cref="ArgumentNullException">
        ///  <paramref name="decompressed"/> is null.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        ///  <paramref name="decompressedLength"/> is less than zero.
        /// </exception>
        /// <exception cref="ZlibException">
        ///  A Zlib error occurred, or the resulting length was greater than <see cref="int.MaxValue"/>.
        /// </exception>
        public static int CompressedLength(byte[] decompressed, int decompressedLength)
        {
            if (decompressed == null)
            {
                throw new ArgumentNullException(nameof(decompressed));
            }
            if (decompressedLength < 0)
            {
                throw ArgumentOutOfRangeUtils.OutsideMin(nameof(decompressedLength), decompressedLength, 0, true);
            }

            int compressedLength = CompressedBounds(decompressedLength);

            byte[]  compressed = new byte[compressedLength];
            ZResult result     = CompressNative(compressed, ref compressedLength, decompressed, decompressedLength);

            if (result != ZResult.OK)            // && result != ZResult.BufferError)
            {
                throw new ZlibException(result, true, decompressed, compressed);
            }

            if (compressedLength < 0)
            {
                throw new ZlibException($"Compressed length of {nameof(decompressedLength)} is greater " +
                                        $"than {nameof(Int32)}.{nameof(int.MaxValue)}!");
            }
            return(compressedLength);
        }
        private static string ResultMessage(ZResult result, bool compress)
        {
            if (compress)
            {
                switch (result)
                {
                case ZResult.MemoryError: return("There was not enough memory to complete the Zlib compression!");

                case ZResult.BufferError: return("The Zlib compressed destination buffer was not large enough!");
                }
            }
            else
            {
                switch (result)
                {
                case ZResult.MemoryError: return("There was not enough memory to complete the Zlib decompression!");

                case ZResult.BufferError: return("The Zlib decompressed destination buffer was not large enough!");

                case ZResult.DataError: return("The Zlib compression data is corrupted or incomplete!");
                }
            }
            return($"Unhandled Zlib error status {result}!");
        }