Skip to content

Standardize pattern for exposing advanced configuration for compression streams #42820

Description

@terrajobst

There is a desire to expose compression-algorithm specific configuration when constructing compression streams. The same options can be used for ZLibStream, DeflateStream, GZipStream. Named those options with Zlib prefix same as the native library name they use another prefix we considered is Deflate - the algorithm name, the prefix needed because we have existing CompressionLevel enum that used for all compression streams including BrotliStream and it cannot be used for fine tuning the compression level for specific stream

publicenumCompressionLevel
{
Optimal=0,
Fastest=1,
NoCompression=2,
SmallestSize=3,
}

API Proposal

namespaceSystem.IO.Compression{publicenumZlibCompressionLevel{DefaultCompression=-1,NoCompression=0,Level1=1,BestSpeed=Level1,Level2=2,Level3=3,Level4=4,Level5=5,Level6=6,Level7=7,Level8=8,Level9=9,BestCompression=Level9,}publicenumZlibCompressionStrategy{DefaultStrategy=0,Filtered=1,HuffmanOnly=2,Rle=3,Fixed=4}publicenumZlibFlushMode{NoFlush=0,PartialFlush=1,SyncFlush=2,FullFlush=3,Finish=4,}publicsealedclassZLibStream:Stream{// CompressionMode.CompresspublicZLibStream(Streamstream,ZlibCompressionLevelcompressionLevel=ZlibCompressionLevel.DefaultCompression,ZlibCompressionStrategystrategy=ZlibCompressionStrategy.DefaultStrategy,boolleaveOpen=false);publicZlibFlushModeFlushMode{get;set;}}publicpartialclassDeflateStream:Stream{publicDeflateStream(Streamstream,ZlibCompressionLevelcompressionLevel=ZlibCompressionLevel.DefaultCompression,ZlibCompressionStrategystrategy=ZlibCompressionStrategy.DefaultStrategy,boolleaveOpen=false);publicZlibFlushModeFlushMode{get;set;}}publicpartialclassGZipStream:Stream{publicGZipStream(Streamstream,ZlibCompressionLevelcompressionLevel=ZlibCompressionLevel.DefaultCompression,ZlibCompressionStrategystrategy=ZlibCompressionStrategy.DefaultStrategy,boolleaveOpen=false){}publicZlibFlushModeFlushMode{get;set;}}publicenumBrotliCompressionQuality{NoCompression,Quality1,Quality2,Quality3,Quality4,Quality5,Quality6,Quality7,Quality8,Quality9,Quality10,Quality11}publicsealedpartialclassBrotliStream:System.IO.Stream{publicBrotliStream(Streamstream,BrotliCompressionQualityquality=BrotliCompressionQuality.Quality4,boolleaveOpen=false){}}}

ZlibCompressionLevel, ZlibCompressionStrategy are only for Compress mode.

Currently ZlibFlushMode.NoFlush used in normal Read/Write operations, ZlibFlushMode.SyncFlush used for Stream.Flush and ZlibFlushMode.Finish is used on dispose. The value set by the new FlushMode property will be used for normal Read/Write operations only.

The MemoryLevel and/or WindowBits options are omitted because there is no ask for them, we could add these and other options if/when they are requested.

API Usage

privateMemoryStreamCompressStream(StreamuncompressedStream){varcompressorOutput=newMemoryStream();using(varcompressionStream=newZLibStream(compressorOutput,compressionLevel:ZlibCompressionLevel.Level5,strategy:ZlibCompressionStrategy.Filtered,leaveOpen:true)){compressionStream.FlushMode=ZlibFlushMode.NoFlush;varbuffer=newbyte[4096];intbytesRead;while((bytesRead=uncompressedStream.Read(buffer,0,buffer.Length))>0){compressionStream.Write(buffer,0,bytesRead);}}compressorOutput.Position=0;returncompressorOutput;}

Alternative Designs

An alternative design would introduce an options type, maybe per each stream, like so:

namespaceSystem.IO.Compression{publicclassBrotliOptions{publicreadonlyBrotliCompressionQualityQuality{get;}publicreadonlyintWindowBits{get;}publicBrotliOptions(BrotliCompressionQualityquality=BrotliCompressionQuality.Level4,intwindowBits=22){}}publicsealedclassBrotliStream:Stream{publicBrotliStream(Streamstream,BrotliOptionsoptions,boolleaveOpen=false);}publicstructZLibOptions{publicintWindowBits{get;}publicZlibMemoryLevelMemoryLevel{get;}publicintCompressionLevel{get;}publicintCompressionStrategy{get;}publicZlibOptions(ZlibCompressionLevelcompressionLevel=ZlibCompressionLevel.DefaultCompression,ZlibCompressionStrategystrategy=ZlibCompressionStrategy.DefaultStrategy,ZlibMemoryLevelmemoryLevel=ZlibMemoryLevel.Level8,intwindowBits=-1);}publicsealedclassZLibStream:Stream{publicZLibStream(Streamstream,ZLibOptionsoptions,boolleaveOpen=false);}publicclassDeflateStream:Stream{publicDeflateStream(Streamstream,ZLibOptionsoptions,boolleaveOpen=false);}publicclassGZipStream:Stream{publicGZipStream(Streamstream,ZLibOptionsoptions,boolleaveOpen=false);}}

We can then decide whether we want to be in the business of defining enums for the underlying types or whether we consider them passthru.

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions