ZStd for .NET

ZStd is a multi-platform .NET wrapper of the library build of Facebook's Zstandard project.
Supported platforms:
- Windows
- Linux
- GNU flavors (Debian, Ubuntu, ...)
- Musl flavors (Alpine, Void, ...)
- Intel x86
- AMD64 / Intel x86-64
- ARMv8-64 / AArch64
- ARMv7-HF / AArch32
- Apple OSX
Note: ARM is support is currently hard-float only, no soft-float platform support unless requested.
Note: In the not too distant future support for 32-bit architectures will likely be dropped.
Features:
- Compression and decompression
- Dictionary support
- Managed streams into streams of frames
- Byte arrays and spans into frames
- Byte arrays and spans into blocks (without frames)
- Generation of dictionaries from a collection of samples
- Loading and saving of dictionaries to and from streams, arrays and spans
- Helpers for collection of dictionary samples and training
- Training will automatically tune unspecified dictionary parameters
Take a look at the unit tests to explore its behavior in different situations.
This is in the middle stages of development, and features may be added over time.
Known Issues:
- Currently the native dependencies are shipped with this NuGet package for all platforms.
Separate NuGet runtime packages should be created to provide each specific platform dependency.
- Coverage currently stands at 50%. Critical path coverage is high.
Coverage of non-critical path operations is low.
- The GC is not yet automatically made aware of unmanaged memory usage.
Acknowlegedments
Official documentation
This project is heavily inspired by ZstdNet, but shares very little in the way of implementation.
Reference
Basic usage examples
Dictionaries
var compressionLevel = 3;
var dict = new ZStdDictionaryBuilder(32 * 1024);
var trainedParams = dict.Train(async () => {
yield return ArraySegment<byte>(trainingData, 7, 42);
}, compressionLevel);
using (var fs = File.Create(path))
dict.WriteTo(fs);
using var cDict = dict.CreateCompressorDictionary(compressionLevel);
using var dDict = dict.CreateDecompressorDictionary();
Compression
using var cCtx = new ZStdCompressor();
cCtx.UseDictionary(cDict);
var compressBufferSize = CCtx.GetUpperBound((UIntPtr) inputData.Length);
var compressBuffer = new byte[compressBufferSize];
cCtx.Set(CompressionParameter.CompressionLevel, compressionLevel);
var compressedSize = cCtx.Compress(compressBuffer, inputData);
var compressedFrame = new ArraySegment<byte>(compressBuffer, 0, (int) compressedSize);
Decompression
var dCtx = new ZStdDecompressor();
dCtx.UseDictionary(dDict);
var decompressBufferSize = DCtx.GetUpperBound(compressedFrame);
var decompressBuffer = new byte[decompressBufferSize];
var decompressedSize = dCtx.Decompress(decompressBuffer, compressedFrame);
var decompressedFrame = new ArraySegment<byte>(decompressBuffer, 0, (int) decompressedSize);
Stream Compression
using var compressed = new MemoryStream();
using var compressStream = new ZStdCompressStream(compressed);
compressStream.Compressor.Set(CompressionParameter.CompressionLevel, compressionLevel);
compressStream.Write(someData);
compressStream.Flush();
Stream Decompression
using var decompressStream = new ZStdDecompressStream(compressedInput);
var decompressed = new byte[someDataSize];
decompressStream.Read(decompressed, 0, decompressed.Length);