Add ZStandard compression support to ZipArchive#124993
Add ZStandard compression support to ZipArchive#124993rzikm wants to merge 2 commits intodotnet:mainfrom
Conversation
Add ZStandard (method 93) as a supported compression method in ZipArchive. This enables reading and writing zip entries compressed with the Zstandard algorithm, which is defined in the ZIP specification (APPNOTE 6.3.10). Changes: - Add ZStandard = 0x5D to ZipCompressionMethod enum - Add ZStandard = 63 to ZipVersionNeededValues - Update GetDataDecompressor/GetDataCompressor to handle ZStandard - Update IsOpenableInitialVerifications to accept ZStandard entries - Update MarkAsModified to preserve ZStandard method (not downgrade to Deflate) - Add unit tests for reading ZStandard-compressed zip entries - Add trimming test to verify ZstandardStream is rooted in trimmed apps Trimming size impact: +19 KB total publish size (+18.5 KB in System.IO.Compression.dll) for rooting ZstandardStream. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add System.IO.Compression.ZipArchive.AllowZStandard feature switch with [FeatureSwitchDefinition] that enables trimming away ZstandardStream when the switch is set to false. Key implementation details: - ZipArchiveSettings.AllowZStandard property with [FeatureSwitchDefinition] - ZstandardStream creation isolated in separate static methods - Feature switch guards use nested if (not &&) for ILLinker compatibility - Trimming tests verify ZstandardStream is present by default and trimmed when switch is disabled Size impact with switch disabled: S.I.C.dll returns to baseline (126 KB), with switch enabled (default): +20 KB delta. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Tagging subscribers to this area: @karelz, @dotnet/area-system-io-compression |
There was a problem hiding this comment.
Pull request overview
Adds support for ZIP compression method 93 (Zstandard) to System.IO.Compression.ZipArchive, including a feature switch intended to allow trimming/AOT scenarios to remove Zstandard-related code when disabled.
Changes:
- Introduces
ZipCompressionMethod.ZStandard(93) and the corresponding “version needed to extract” constant. - Updates
ZipArchiveEntryread/write/update handling to recognize and (when enabled) useZstandardStreamfor method 93 entries. - Adds unit tests for reading/updating Zstandard entries and a trimming test that verifies
ZstandardStreamcan be trimmed when the feature switch is disabled.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/libraries/System.IO.Compression/tests/ZipArchive/zip_ReadTests.cs | Adds Zstandard ZIP test vectors and read/update validation. |
| src/libraries/System.IO.Compression/tests/TrimmingTests/ZstandardStreamDisabledTrimmedTest.cs | Adds console app trimming test for feature-switch-disabled scenario. |
| src/libraries/System.IO.Compression/tests/TrimmingTests/System.IO.Compression.TrimmingTests.proj | Registers the new trimming test app and disables the feature switch for it. |
| src/libraries/System.IO.Compression/src/System/IO/Compression/ZipVersion.cs | Adds ZipVersionNeededValues.ZStandard = 63. |
| src/libraries/System.IO.Compression/src/System/IO/Compression/ZipCompressionMethod.cs | Adds ZipCompressionMethod.ZStandard = 0x5D. |
| src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveSettings.cs | Adds AppContext feature switch plumbing (AllowZstandard). |
| src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs | Integrates Zstandard into compression/decompression/openability/update-mode behavior. |
| src/libraries/System.IO.Compression/src/System.IO.Compression.csproj | Includes ZipArchiveSettings.cs in the build. |
| src/libraries/System.IO.Compression/ref/System.IO.Compression.cs | Updates reference contract to include ZipCompressionMethod.ZStandard = 93. |
| if (args.Length > 0) | ||
| { | ||
| ZipFile.ExtractToDirectory(args[0], args[1]); | ||
|
|
||
| return 100; | ||
| } |
There was a problem hiding this comment.
args.Length > 0 is insufficient here because the code accesses args[1]. If the harness ever passes only one argument, this will throw IndexOutOfRangeException. Check for args.Length >= 2 (or validate both paths) before calling ZipFile.ExtractToDirectory(args[0], args[1]).
| [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] | ||
| [MemberData(nameof(Get_Booleans_Data))] | ||
| public static async Task ZStandard_ReadEntryData_Succeeds(bool async) | ||
| { |
There was a problem hiding this comment.
These Zstandard ZIP tests are only guarded by IsNotBrowser, but ZstandardStream is also marked [UnsupportedOSPlatform("wasi")] and will throw PlatformNotSupportedException there. Add nameof(PlatformDetection.IsNotWasi) (or an equivalent WASM/WASI exclusion) so the test doesn't fail on WASI runs.
| [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] | ||
| [MemberData(nameof(Get_Booleans_Data))] | ||
| public static async Task ZStandard_UpdateEntry_PreservesCompressionMethod(bool async) | ||
| { |
There was a problem hiding this comment.
This test excludes Browser but not WASI. Since ZstandardStream is [UnsupportedOSPlatform("wasi")], attempting to update/read back Zstandard entries will throw PlatformNotSupportedException on WASI. Add nameof(PlatformDetection.IsNotWasi) (or equivalent) to the ConditionalTheory guard.
Feature switches have poor usability. They should be thought about as solutions of last resort for mistakes in API design that we cannot fix. Our primary solutions should be API based where possible. |
Resolves #123532
Summary
This PR adds ZStandard (method 93) compression support to
ZipArchive, allowing reading, writing, and updating of ZStandard-compressed entries.Changes
ZipCompressionMethod.ZStandard = 93enum value (per APPNOTE 6.3.10)ZipVersionNeededValues.ZStandard = 63version constantZipArchiveEntryto handle ZStandard in decompression, compression, openability checks, and update-mode preservationSystem.IO.Compression.ZipArchive.AllowZstandard(default:true) that allows the ILLinker/NativeAOT to trim away all ZStandard-related code when set tofalseFeature Switch
The
System.IO.Compression.ZipArchive.AllowZstandardfeature switch controls whether ZStandard support is included in trimmed/NativeAOT applications. Applications that don't need ZStandard ZIP support can set it tofalseto reduce binary size.To disable:
Size Impact
Measured on a minimal test application that calls
ZipFile.ExtractToDirectory:The IL trimming overhead is modest (+20 KB). The NativeAOT overhead is larger (~1.3 MB) because the native zstd interop layer and all related types are compiled to native code. The feature switch fully eliminates this overhead when disabled.