/*
* 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()
);
}
}
}
}