Skip to content

Add ZStandard compression support to ZipArchive#124993

Draft
rzikm wants to merge 2 commits intodotnet:mainfrom
rzikm:zip-zstd
Draft

Add ZStandard compression support to ZipArchive#124993
rzikm wants to merge 2 commits intodotnet:mainfrom
rzikm:zip-zstd

Conversation

@rzikm
Copy link
Member

@rzikm rzikm commented Feb 27, 2026

Resolves #123532

Summary

This PR adds ZStandard (method 93) compression support to ZipArchive, allowing reading, writing, and updating of ZStandard-compressed entries.

Changes

  • Added ZipCompressionMethod.ZStandard = 93 enum value (per APPNOTE 6.3.10)
  • Added ZipVersionNeededValues.ZStandard = 63 version constant
  • Updated ZipArchiveEntry to handle ZStandard in decompression, compression, openability checks, and update-mode preservation
  • Added a feature switch System.IO.Compression.ZipArchive.AllowZstandard (default: true) that allows the ILLinker/NativeAOT to trim away all ZStandard-related code when set to false
  • Added unit tests for reading and round-tripping ZStandard entries
  • Added trimming test verifying ZstandardStream is removed when the switch is disabled

Feature Switch

The System.IO.Compression.ZipArchive.AllowZstandard feature switch controls whether ZStandard support is included in trimmed/NativeAOT applications. Applications that don't need ZStandard ZIP support can set it to false to reduce binary size.

To disable:

<RuntimeHostConfigurationOption Include="System.IO.Compression.ZipArchive.AllowZstandard" Value="false" Trim="true" />

Size Impact

Measured on a minimal test application that calls ZipFile.ExtractToDirectory:

Configuration IL Trimmed (S.I.C.dll) IL Trimmed (total publish) NativeAOT binary
ZStandard enabled (default) 145.5 KB 39.17 MB 2,297 KB
ZStandard disabled (switch off) 126 KB 39.15 MB 1,012 KB
Delta +19.5 KB +20 KB +1,285 KB

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.

rzikm and others added 2 commits February 27, 2026 16:11
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>
Copilot AI review requested due to automatic review settings February 27, 2026 23:06
@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to this area: @karelz, @dotnet/area-system-io-compression
See info in area-owners.md if you want to be subscribed.

@rzikm
Copy link
Member Author

rzikm commented Feb 27, 2026

cc @ericstj, @jkotas

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 ZipArchiveEntry read/write/update handling to recognize and (when enabled) use ZstandardStream for method 93 entries.
  • Adds unit tests for reading/updating Zstandard entries and a trimming test that verifies ZstandardStream can 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.

Comment on lines +12 to +17
if (args.Length > 0)
{
ZipFile.ExtractToDirectory(args[0], args[1]);

return 100;
}
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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]).

Copilot uses AI. Check for mistakes.
Comment on lines +921 to +924
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
[MemberData(nameof(Get_Booleans_Data))]
public static async Task ZStandard_ReadEntryData_Succeeds(bool async)
{
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +938 to +941
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
[MemberData(nameof(Get_Booleans_Data))]
public static async Task ZStandard_UpdateEntry_PreservesCompressionMethod(bool async)
{
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
@jkotas
Copy link
Member

jkotas commented Feb 27, 2026

Added a feature switch System.IO.Compression.ZipArchive.AllowZstandard (default: true) that allows the ILLinker/NativeAOT to trim away all ZStandard-related code when set to false

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support Zstandard compression in ZipArchives

3 participants