/* * Copyright (c) 2024 Vaughn Nugent * * Library: VNLib * Package: VNLib.Net.Compression * File: NativeCompressionLib.cs * * NativeCompressionLib.cs is part of VNLib.Net.Compression which is part of * the larger VNLib collection of libraries and utilities. * * VNLib.Net.Compression is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 2 of the License, * or (at your option) any later version. * * VNLib.Net.Compression is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with VNLib.Net.Compression. If not, see http://www.gnu.org/licenses/. */ using System; using System.IO.Compression; using System.Runtime.InteropServices; using VNLib.Net.Http; using VNLib.Utils; using VNLib.Utils.Extensions; namespace VNLib.Net.Compression { /// /// A referrence native compression library implementation. Allows for creating compressor instances /// from a native dll. /// public sealed class NativeCompressionLib : VnDisposeable, INativeCompressionLib { private readonly LibraryWrapper _library; private NativeCompressionLib(LibraryWrapper nativeLib) => _library = nativeLib; /// protected override void Free() => _library.Dispose(); /// /// Loads the native compression DLL at the specified file path and search pattern /// /// The path (relative or absolute) path to the native dll to load /// The dll search pattern /// A new library handle public static NativeCompressionLib LoadLibrary(string libPath, DllImportSearchPath searchPath) { LibraryWrapper wrapper = LibraryWrapper.LoadLibrary(libPath, searchPath); return new NativeCompressionLib(wrapper); } /// /// public CompressionMethod GetSupportedMethods() { Check(); return _library.GetSupportedMethods(); } /// /// public INativeCompressor AllocCompressor(CompressionMethod method, CompressionLevel level) { #pragma warning disable CA2000 // Dispose objects before losing scope SafeHandle libHandle = AllocSafeCompressorHandle(method, level); return new Compressor(_library, libHandle); #pragma warning restore CA2000 // Dispose objects before losing scope } /// /// public SafeHandle AllocSafeCompressorHandle(CompressionMethod method, CompressionLevel level) { Check(); //Alloc compressor then craete a safe handle IntPtr comp = _library.AllocateCompressor(method, level); return new SafeCompressorHandle(_library, comp); } internal sealed record class Compressor(LibraryWrapper LibComp, SafeHandle CompressorHandle) : INativeCompressor { /// public CompressionResult Compress(ReadOnlyMemory input, Memory output) { CompressorHandle.ThrowIfClosed(); return LibComp.CompressBlock( CompressorHandle.DangerousGetHandle(), output, input, finalBlock: false ); } /// public CompressionResult Compress(ReadOnlySpan input, Span output) { CompressorHandle.ThrowIfClosed(); return LibComp.CompressBlock( CompressorHandle.DangerousGetHandle(), output, input, finalBlock: false ); } /// public void Dispose() => CompressorHandle.Dispose(); /// public int Flush(Memory buffer) { CompressorHandle.ThrowIfClosed(); CompressionResult result = LibComp.CompressBlock( CompressorHandle.DangerousGetHandle(), buffer, input: default, finalBlock: true ); return result.BytesWritten; } /// public int Flush(Span buffer) { CompressorHandle.ThrowIfClosed(); CompressionResult result = LibComp.CompressBlock( CompressorHandle.DangerousGetHandle(), buffer, input: default, finalBlock: true ); return result.BytesWritten; } /// public uint GetBlockSize() { CompressorHandle.ThrowIfClosed(); return LibComp.GetBlockSize( CompressorHandle.DangerousGetHandle() ); } /// public uint GetCompressedSize(uint size) { CompressorHandle.ThrowIfClosed(); return (uint)LibComp.GetOutputSize( CompressorHandle.DangerousGetHandle(), size, flush: 1 //truthy enables flushing ); } /// public CompressionLevel GetCompressionLevel() { CompressorHandle.ThrowIfClosed(); return LibComp.GetCompressorLevel( CompressorHandle.DangerousGetHandle() ); } /// public CompressionMethod GetCompressionMethod() { CompressorHandle.ThrowIfClosed(); return LibComp.GetCompressorType( CompressorHandle.DangerousGetHandle() ); } } } }