Add parameterized CRC-32 and CRC-64#124117
Conversation
byte-by-byte table lookup, except for the `Crc32` and `Crc64` parameter sets, which defer to the already-optimized implementations, and CRC-32/C, which uses x86 and ARM intrinsics. Generalized vectorization will be done as a followup.
|
Tagging subscribers to this area: @dotnet/area-system-io-hashing, @bartonjs, @vcsjones |
There was a problem hiding this comment.
Pull request overview
Adds support for computing CRC-32 and CRC-64 using caller-specified parameter sets, while keeping the existing optimized implementations for the default CRC-32 / CRC-64 variants (and CRC-32C via intrinsics where available). This expands System.IO.Hashing to cover additional CRC variants requested in #123164.
Changes:
- Introduce
Crc32ParameterSet/Crc64ParameterSettypes with factory creation and a small set of well-known presets (e.g., CRC-32, CRC-32C, CRC-64, CRC-64/NVME). - Add parameterized overloads/constructors on
Crc32andCrc64that accept a parameter set, and route hashing through the parameter set implementation. - Add extensive new test coverage for parameterized CRC-32/CRC-64 variants and known-answer tests for well-known parameter sets.
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32.cs | Adds Crc32ParameterSet constructor/property and parameterized Hash/TryHash/HashToUInt32 overloads; routes computation through parameter set. |
| src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc64.cs | Adds Crc64ParameterSet constructor/property and parameterized Hash/TryHash/HashToUInt64 overloads; routes computation through parameter set. |
| src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32ParameterSet.cs | Introduces core CRC-32 parameter set type (properties, Create, finalization, byte-order write). |
| src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32ParameterSet.Table.cs | Implements table-based CRC-32 update for reflected and forward modes. |
| src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32ParameterSet.WellKnown.cs | Adds well-known CRC-32 and CRC-32C parameter sets, including intrinsic-based CRC-32C path. |
| src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc64ParameterSet.cs | Introduces core CRC-64 parameter set type (properties, Create, finalization, byte-order write). |
| src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc64ParameterSet.Table.cs | Implements table-based CRC-64 update for reflected and forward modes. |
| src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc64ParameterSet.WellKnown.cs | Adds well-known CRC-64 (ECMA-182) and CRC-64/NVME parameter sets. |
| src/libraries/System.IO.Hashing/src/System.IO.Hashing.csproj | Adds new parameter set sources to the build. |
| src/libraries/System.IO.Hashing/ref/System.IO.Hashing.cs | Updates the public reference surface for new parameter set types and overloads. |
| src/libraries/System.IO.Hashing/tests/System.IO.Hashing.Tests.csproj | Includes new test sources for parameterized CRC testing. |
| src/libraries/System.IO.Hashing/tests/Crc32Tests.cs | Adds argument-null validation tests for new CRC-32 parameterSet overloads/ctor. |
| src/libraries/System.IO.Hashing/tests/Crc32ParameterSetTests.cs | Adds known-answer tests for several CRC-32 parameter sets. |
| src/libraries/System.IO.Hashing/tests/Crc32Tests_Parameterized.cs | Adds parameterized driver-based test framework for CRC-32 parameter sets. |
| src/libraries/System.IO.Hashing/tests/Crc32Tests_ParameterSet_Crc32.cs | Adds CRC-32 parameter set driver + singleton/value tests. |
| src/libraries/System.IO.Hashing/tests/Crc32Tests_ParameterSet_Crc32C.cs | Adds CRC-32C parameter set driver + singleton/value tests. |
| src/libraries/System.IO.Hashing/tests/Crc32Tests_ParameterSet_Custom.cs | Adds custom CRC-32 parameter set drivers using Create(...). |
| src/libraries/System.IO.Hashing/tests/Crc64ParameterSetTests.cs | Adds known-answer tests for several CRC-64 parameter sets. |
| src/libraries/System.IO.Hashing/tests/Crc64Tests_Parameterized.cs | Adds parameterized driver-based test framework for CRC-64 parameter sets. |
| src/libraries/System.IO.Hashing/tests/Crc64Tests_Parameterized_Crc64.cs | Adds CRC-64 parameter set driver + singleton/value tests. |
| src/libraries/System.IO.Hashing/tests/Crc64Tests_Parameterized_Custom.cs | Adds a custom CRC-64 parameter set driver using Create(...). |
| src/libraries/System.IO.Hashing/tests/Crc64Tests_Parameterized_Nvme.cs | Adds CRC-64/NVME parameter set driver + singleton/value tests. |
src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32ParameterSet.WellKnown.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32ParameterSet.WellKnown.cs
Outdated
Show resolved
Hide resolved
stephentoub
left a comment
There was a problem hiding this comment.
Code Review: PR #124117 - Add parameterized CRC-32 and CRC-64
Holistic Assessment
Motivation: This PR addresses issue #123164 by adding parameterized CRC-32 and CRC-64 support, allowing users to specify custom polynomials, initial values, final XOR values, and reflection settings. This is a valuable addition as different protocols use different CRC parameters.
Approach: The implementation introduces Crc32ParameterSet and Crc64ParameterSet abstract classes that encapsulate CRC parameters and computation logic. Well-known parameter sets (IEEE 802.3, CRC-32C, ECMA-182, NVMe) are provided as static properties, and custom parameter sets can be created via a factory method. The existing Crc32 and Crc64 classes are extended with constructor and static method overloads that accept parameter sets.
Net Positive: ✅ Yes - This is a well-structured, backward-compatible extension that significantly increases the utility of the hashing library.
Detailed Findings
✅ Correctness
-
Known-answer tests: Comprehensive testing against the CRC catalogue at reveng.sourceforge.io with multiple parameter sets (AIXM, AUTOSAR, BZIP2, ISCSI, CKSUM, etc.).
-
Residue verification: Tests properly verify the CRC residue property which validates the algorithm correctness.
-
Optimized paths preserved: The existing vectorized implementations for CRC-32 (IEEE 802.3) and CRC-64 (ECMA-182) are correctly preserved through dedicated parameter set classes that delegate to the optimized
Updatemethods. -
Hardware acceleration for CRC-32C: x86 SSE4.2 and ARM CRC32 intrinsics are correctly used when available.
⚠️ Issues to Address
-
Missing XML documentation on
Crc64ParameterSet.Crc64andCrc64ParameterSet.Nvmeproperties (Crc64ParameterSet.WellKnown.cs lines 8-12):
TheCrc32ParameterSethas full XML documentation for its static properties, butCrc64ParameterSet.Crc64andCrc64ParameterSet.Nvmelack XML doc comments. For API consistency and IntelliSense support, these should be documented similarly to their CRC-32 counterparts. -
Inconsistent
[CLSCompliant(false)]attribute onCrc64.Hashoverload (ref/System.IO.Hashing.cs line 63-64):
TheCrc64.Hash(Crc64ParameterSet parameterSet, ReadOnlySpan<byte> source, Span<byte> destination)method has[CLSCompliant(false)]in the ref assembly, but the correspondingCrc32.Hashoverload (line 23) does not have this attribute. This appears to be an inconsistency - neither should need it since they just returnintand take spans. Please verify this is intentional. -
Base class declared with different modifiers in different files (Crc32ParameterSet.cs line 8 vs ref assembly line 34):
InCrc32ParameterSet.cs, the class is declared aspublic partial class Crc32ParameterSetbut the ref assembly andCrc32ParameterSet.WellKnown.csdeclare it aspublic abstract partial class Crc32ParameterSet. The main file is missing theabstractkeyword. While this may compile (partial classes merge modifiers), it should be consistent for clarity.
💡 Suggestions (Non-blocking)
-
Consider caching well-known Nvme parameter set with a dedicated class:
Crc64ParameterSet.Nvmecreates the parameter set viaCreate(), which generates a new lookup table each time. Consider using thefield ??=pattern with a dedicated class (likeIeee8023ParameterSet) if NVMe CRC is expected to be used frequently, to avoid repeated table generation. -
Switch expression simplification (Crc32ParameterSet.cs lines 59-65):
csharp Crc32ParameterSet set = reflectValues switch { false => new ForwardTableBasedCrc32(polynomial, initialValue, finalXorValue), _ => new ReflectedTableBasedCrc32(polynomial, initialValue, finalXorValue), }; return set;
Could be simplified to:
csharp return reflectValues ? new ReflectedTableBasedCrc32(polynomial, initialValue, finalXorValue) : new ForwardTableBasedCrc32(polynomial, initialValue, finalXorValue); -
Test file BOM characters: The new test files have Unicode BOM (
\u{feff}) at the start. This is generally fine but worth noting for consistency with other test files in the repository.
Cross-cutting Analysis
-
API Surface: The new APIs follow the existing patterns in the library (static Hash methods, TryHash, instance-based streaming). The parameter sets are immutable and thread-safe.
-
Performance: Default/well-known parameter sets use optimized code paths. Custom parameter sets use byte-by-byte table lookup which is reasonable for the initial implementation; the PR description mentions vectorization as a planned follow-up.
-
Backward Compatibility: ✅ Existing APIs continue to work unchanged with the same behavior.
Test Quality
✅ Excellent test coverage including:
- Parameter set property verification
- Known-answer tests from the CRC catalogue
- Residue tests validating mathematical properties
- Null argument validation
- Singleton verification for well-known parameter sets
- Tests for both reflected and forward (non-reflected) CRC variants
Summary
Verdict: ✅ Approve with minor changes
This is a well-designed, thoroughly-tested feature addition. The implementation correctly preserves existing optimizations while adding flexible parameterization. Please address the missing XML documentation on Crc64ParameterSet properties and verify the [CLSCompliant(false)] inconsistency before merging.
src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32ParameterSet.WellKnown.cs
Show resolved
Hide resolved
src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc64ParameterSet.WellKnown.cs
Show resolved
Hide resolved
src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32ParameterSet.cs
Show resolved
Hide resolved
src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc64ParameterSet.cs
Show resolved
Hide resolved
🤖 Copilot Code Review — PR #124117Holistic AssessmentMotivation: ✅ This PR addresses a genuine need identified in issue #123164 (api-approved). Multiple CRC variants exist (NVMe, CRC-32C, CKSUM, BZIP2, etc.) and users currently must implement their own CRC calculations for non-standard variants. The request to support parameterized CRCs is well-justified. Approach: ✅ The design is sound. It introduces Summary: ✅ LGTM with minor suggestions. This is a well-structured, backward-compatible feature addition with comprehensive test coverage. The code correctly preserves existing optimizations for standard CRC variants. The few observations below are minor and non-blocking. Detailed Findings✅ Correctness — Verified
✅ API Design — Consistent
✅ Thread Safety — AcceptableThe ✅ Test Coverage — Excellent
💡 Minor Suggestions (Non-blocking)
Cross-cutting Analysis
Review performed with code-review skill, models: Claude Sonnet 4, Gemini 3 Pro |
|
@stephentoub By the way, your additional code reviewer skill is hallucinating:
That isn't public API, and doesn't exist in core as non-public API. Maybe it used to as non-public... but it's definitely not something that can be called. |
src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32ParameterSet.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32ParameterSet.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32ParameterSet.cs
Show resolved
Hide resolved
src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32ParameterSet.WellKnown.cs
Show resolved
Hide resolved
src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc64ParameterSet.cs
Show resolved
Hide resolved
src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32ParameterSet.cs
Show resolved
Hide resolved
|
/ba-g timeout |
Add parameterized CRC-32 and CRC-64. Currently, they are just done as
byte-by-byte table lookup, except for the
Crc32andCrc64parametersets, which defer to the already-optimized implementations, and CRC-32/C,
which uses x86 and ARM intrinsics.
Generalized vectorization will be done as a followup.
Fixes #123164, #85222, and #78063.