ZstdNet

repository·master·Indexed 43 days ago

https://github.com/skbkontur/zstdnet

A .NET wrapper for the Zstandard (zstd) native compression library. It provides high-performance, lossless compression and decompression for byte arrays, spans, and streams, including support for dictionary-based compression via DictBuilder. Supports netstandard2.0 and netstandard2.1 with pre-built native libraries for Windows, Linux, and macOS.

Tokens
1.9K
Snippets
6
Records
10
Agent score
6%

What's inside ZstdNet

  1. Overview of ZstdNet features

    master

    ZstdNet provides high-performance compression and decompression capabilities using the Zstandard (zstd) algorithm. Key features include:

    • Data Types: Compression and decompression of byte arrays (byte[]) and Span<byte>.
    • Streaming: Support for streaming compression and decompression.
    • Configuration: Support for advanced compression parameters.
    • Dictionaries: Generation and use of dictionaries for optimized compression of small data sets.
  2. Install ZstdNet via NuGet

    master

    ZstdNet is a .NET wrapper for the Zstd native library, supporting netstandard2.{0|1}. It includes pre-built native shared libraries for Windows (win), Linux (linux), and macOS (osx).

    Platform Support and Runtime Resolution

    • .NET Core / .NET 5+: Uses the standard dotnet runtime identifier (RID) resolution mechanism.
    • .NET Framework: Uses a fallback mechanism that requires you to explicitly select the platform (x86, x64, or ARM64).
    • Windows: Uses the static VC runtime.

    Resolving Native Dependencies at Runtime

    If the native library is not automatically found, you can resolve it manually:

    • For .NET Core/5+: Use NativeLibrary.SetDllImportResolver.
    • For .NET Framework: Use SetDllDirectory from kernel32.dll.
  3. Handle ZstdNet exceptions

    master

    The wrapper throws ZstdException if there is malformed data or an error within the underlying libzstd.

    A common error is ZSTD_error_dstSize_tooSmall, which occurs if the provided destination buffer is too small for the operation.

  4. Configure compression with CompressionOptions

    master

    The CompressionOptions class stores compression settings and dictionary information.

    Important Notes:

    • Thread Safety: Instances are thread-safe and can be shared across threads to reduce overhead.
    • Lifecycle: Implements IDisposable. Call Dispose() to avoid finalizer thread loading.

    Configuration Options:

    • byte[] dict: A compression dictionary (can be loaded from a file or generated via DictBuilder).
    • int compressionLevel: Range from CompressionOptions.MinCompressionLevel to CompressionOptions.MaxCompressionLevel (currently 22). Default is 3.
    • IReadOnlyDictionary<ZSTD_cParameter, int> advancedParams: Allows setting specific parameters like multi-threading or long-distance matching mode.
    using var options = new CompressionOptions(dict, compressionLevel: 5);
    using var compressor = new Compressor(options);
    var compressedData = compressor.Wrap(sourceData);
  5. Generate a compression dictionary with DictBuilder

    master

    The DictBuilder static class allows you to train a compression dictionary from a collection of data samples.

    Method:

    • TrainFromBuffer(IEnumerable<byte[]> samples, int dictCapacity = DefaultDictCapacity): Generates a dictionary from the provided samples.

    Options:

    • int dictCapacity: The maximum dictionary size in bytes. Defaults to DictBuilder.DefaultDictCapacity (currently 110 KiB).
  6. Configure decompression with DecompressionOptions

    master

    The DecompressionOptions class stores decompression settings and dictionary information.

    Important Notes:

    • Thread Safety: Instances are thread-safe and can be shared across threads.
    • Lifecycle: Implements IDisposable.

    Configuration Options:

    • byte[] dict: A compression dictionary.
    • IReadOnlyDictionary<ZSTD_dParameter, int> advancedParams: Advanced parameters such as maximum memory usage.
    using var options = new DecompressionOptions(dict);
    using var decompressor = new Decompressor(options);
    var decompressedData = decompressor.Unwrap(compressedData);
  7. Use the Compressor class for block compression

    master

    The Compressor class provides block-based compression.

    Important Notes:

    • Thread Safety: Instances are not thread-safe. Use ThreadStatic or a pool of compressors for bulk processing.
    • Lifecycle: Implements IDisposable. Always use using or call Dispose() to avoid pressure on the finalizer thread.
    • Large Buffers: For buffers close to 2GB, Wrap is only reliable if GetCompressBoundLong(size) <= 0x7FFFFFC7. For larger data, use the CompressionStream API.

    Methods:

    • Wrap(...): Compresses data into a new buffer or an existing one. Supports byte[], ArraySegment<byte>, ReadOnlySpan<byte>, and Span<byte>.
    • GetCompressBound(int size): Returns the required destination buffer size for a given source size.
    • GetCompressBoundLong(ulong size): Returns the required destination buffer size for a given source size (ulong).
    using var compressor = new Compressor();
    var compressedData = compressor.Wrap(sourceData);
  8. Use DecompressionStream for streaming decompression

    master

    The DecompressionStream class implements read-only streaming decompression. It uses ArrayPool<byte>.Shared.Rent() for its internal buffer.

    Lifecycle: Implements IDisposable and IAsyncDisposable. Use await using for asynchronous workflows.

    Constructor Parameters:

    • Stream stream: The input stream for reading raw data.
    • DecompressionOptions options: Decompression settings (defaults to null).
    • int bufferSize: The size of the decompression buffer. Defaults to the result of ZSTD_DStreamInSize (~128KB).
    await using var decompressionStream = new DecompressionStream(inputStream, zstdBufferSize);
    await decompressionStream.CopyToAsync(outputStream, copyBufferSize);
  9. Use CompressionStream for streaming compression

    master

    The CompressionStream class implements write-only streaming compression. It uses ArrayPool<byte>.Shared.Rent() for its internal buffer.

    Lifecycle: Implements IDisposable and IAsyncDisposable. Use await using for asynchronous workflows.

    Constructor Parameters:

    • Stream stream: The output stream for writing compressed data.
    • CompressionOptions options: Compression settings (defaults to CompressionOptions.Default).
    • int bufferSize: The size of the compression buffer. Defaults to the result of ZSTD_CStreamOutSize (~128KB), which ensures at least one complete compressed block is flushed.
    await inputStream.CopyToAsync(compressionStream, copyBufferSize);
  10. Use the Decompressor class for block decompression

    master

    The Decompressor class provides block-based decompression.

    Important Notes:

    • Thread Safety: Instances are not thread-safe. Use ThreadStatic or a pool for bulk processing.
    • Lifecycle: Implements IDisposable.
    • Buffer Safety: When using Unwrap with a new buffer, data can only be saved if a field with the decompressed size is present in the compressed data. You can limit the size using maxDecompressedSize to protect against untrusted data.
    • Precheck: If bufferSizePrecheck is true, the destination buffer size is checked against the decompressed field length before decompression begins.

    Methods:

    • Unwrap(...): Decompresses data into a new or existing buffer. Supports byte[], ArraySegment<byte>, ReadOnlySpan<byte>, and Span<byte>.
    • GetDecompressedSize(...): Reads the decompressed data size field from the compressed source.
    using var decompressor = new Decompressor();
    var decompressedData = decompressor.Unwrap(compressedData);