Background and motivation
The new Zstandard APIs provide a way to configure the ZstandardEncoder with ZstandardCompressionOptions, but there is no symmetric options for ZstandardDecoder. This is problematic in case user wants to configure maxWindowLog on a decompressing ZstandardStream. Currently, it is possible by passing ZstandardStream a pre-configured ZstandardDecoder:
var decoder = new ZstandardDecoder(dictionary, maxWindowLog);
var stream = new ZstandardStream(decoder);
However, in this case, ZstandardStream does not own the ZstandardDecoder instance, and caller is responsible for disposing it (or reusing it in the future). But this may be difficult for some scenarios, consider e.g. ASP.NET Core decompression middleware:
internal sealed class ZstandardDecompressionProvider : IDecompressionProvider
{
/// <inheritdoc />
public Stream GetDecompressionStream(Stream stream)
{
var decoder = new ZstandardDecoder(dictionary, maxWindowLog);
return new ZstandardStream(stream, decoder, leaveOpen: true);
}
}
There is no good way to tie the decoder's lifetime to the stream, except creating another wrapper stream, or leaving it to be GC'd.
API Proposal
namespace System.IO.Compression;
public class ZstandardDecompressionOptions
{
public ZstandardDictionary? Dictionary { get; set; }
// Value 0 indicates the implementation-defined default window size.
// range from ZstandardCompressionOptions.MinWindowLog - MaxWindowLog
public int MaxWindowLog { get; set; }
}
public partial class ZstandardDecoder
{
// not strictly necessary, other ctors can be used
public ZstandardDecoder(ZstandardDecompressionOptions decompressionOptions);
}
public partial class ZstandardStream
{
// symmetric to ZstandardStream(Stream! stream, ZstandardCompressionOptions! compressionOptions, bool leaveOpen = false);
public ZstandardStream(Stream stream, ZstandardDecompressionOptions decompressionOptions, bool leaveOpen = false);
}
API Usage
ASP.NET Core can benefit from this and allow configuring maxWindowLog in incoming request decompression:
internal sealed class ZstandardDecompressionProvider : IDecompressionProvider
{
// configured by the app code
public ZstandardDecompressionOptions Options { get; set; }
/// <inheritdoc />
public Stream GetDecompressionStream(Stream stream)
{
return new ZstandardStream(stream, Options, leaveOpen: true);
}
}
This would otherwise be difficult, because ZstandardDecompressionProvider would need to pass in a configured ZstandardDecoder, and then there is question of disposing the decoder.
Alternative Designs
Allow specifying whether ZstandardStream takes over the ownership of passed in ZstandardEncoder/Decoder:
public partial class ZstandardStream
{
public ZstandardStream(Stream stream, ZstandardEncoder encoder, bool leaveOpen = false, bool shouldDisposeEncoder);
public ZstandardStream(Stream stream, ZstandardDecoder decoder, bool leaveOpen = false, bool shouldDisposeDecoder);
}
Risks
No response
Background and motivation
The new Zstandard APIs provide a way to configure the
ZstandardEncoderwithZstandardCompressionOptions, but there is no symmetric options forZstandardDecoder. This is problematic in case user wants to configuremaxWindowLogon a decompressingZstandardStream. Currently, it is possible by passingZstandardStreama pre-configuredZstandardDecoder:However, in this case,
ZstandardStreamdoes not own theZstandardDecoderinstance, and caller is responsible for disposing it (or reusing it in the future). But this may be difficult for some scenarios, consider e.g. ASP.NET Core decompression middleware:There is no good way to tie the decoder's lifetime to the stream, except creating another wrapper stream, or leaving it to be GC'd.
API Proposal
API Usage
ASP.NET Core can benefit from this and allow configuring
maxWindowLogin incoming request decompression:This would otherwise be difficult, because
ZstandardDecompressionProviderwould need to pass in a configuredZstandardDecoder, and then there is question of disposing the decoder.Alternative Designs
Allow specifying whether ZstandardStream takes over the ownership of passed in ZstandardEncoder/Decoder:
Risks
No response