@@ -144,12 +144,14 @@ pub enum CrcAlgorithm {
144
144
Crc32Bzip2 ,
145
145
Crc32CdRomEdc ,
146
146
Crc32Cksum ,
147
+ Crc32Custom , // Custom CRC-32 implementation, not defined in consts
147
148
Crc32Iscsi ,
148
149
Crc32IsoHdlc ,
149
150
Crc32Jamcrc ,
150
151
Crc32Mef ,
151
152
Crc32Mpeg2 ,
152
153
Crc32Xfer ,
154
+ Crc64Custom , // Custom CRC-64 implementation, not defined in consts
153
155
Crc64Ecma182 ,
154
156
Crc64GoIso ,
155
157
Crc64Ms ,
@@ -480,6 +482,52 @@ pub fn checksum_combine(
480
482
combine:: checksums ( checksum1, checksum2, checksum2_len, params)
481
483
}
482
484
485
+ /// Combines two CRC checksums using the custom specified parameters.
486
+ pub fn checksum_combine_with_custom_params (
487
+ params : CrcParams ,
488
+ checksum1 : u64 ,
489
+ checksum2 : u64 ,
490
+ checksum2_len : u64 ,
491
+ ) -> u64 {
492
+ combine:: checksums ( checksum1, checksum2, checksum2_len, params)
493
+ }
494
+
495
+ /// Returns the custom CRC parameters for a given set of Rocksoft CRC parameters.
496
+ ///
497
+ /// Does not support mis-matched refin/refout parameters, so both must be true or both false.
498
+ ///
499
+ /// Rocksoft parameters for lots of variants: https://reveng.sourceforge.io/crc-catalogue/all.htm
500
+ pub fn get_custom_params (
501
+ name : & ' static str ,
502
+ width : u8 ,
503
+ poly : u64 ,
504
+ init : u64 ,
505
+ reflected : bool ,
506
+ xorout : u64 ,
507
+ check : u64 ,
508
+ ) -> CrcParams {
509
+ let keys = generate:: keys ( width, poly, reflected) ;
510
+
511
+ let algorithm = match width {
512
+ 32 => CrcAlgorithm :: Crc32Custom ,
513
+ 64 => CrcAlgorithm :: Crc64Custom ,
514
+ _ => panic ! ( "Unsupported width: {}" , width) ,
515
+ } ;
516
+
517
+ CrcParams {
518
+ algorithm,
519
+ name,
520
+ width,
521
+ poly,
522
+ init,
523
+ refin : reflected,
524
+ refout : reflected,
525
+ xorout,
526
+ check,
527
+ keys,
528
+ }
529
+ }
530
+
483
531
/// Returns the target used to calculate the CRC checksum for the specified algorithm.
484
532
///
485
533
/// These strings are informational only, not stable, and shouldn't be relied on to match across
@@ -505,12 +553,18 @@ fn get_calculator_params(algorithm: CrcAlgorithm) -> (CalculatorFn, CrcParams) {
505
553
CrcAlgorithm :: Crc32Bzip2 => ( Calculator :: calculate as CalculatorFn , CRC32_BZIP2 ) ,
506
554
CrcAlgorithm :: Crc32CdRomEdc => ( Calculator :: calculate as CalculatorFn , CRC32_CD_ROM_EDC ) ,
507
555
CrcAlgorithm :: Crc32Cksum => ( Calculator :: calculate as CalculatorFn , CRC32_CKSUM ) ,
556
+ CrcAlgorithm :: Crc32Custom => {
557
+ panic ! ( "Custom CRC-32 requires parameters via get_custom_params()" )
558
+ }
508
559
CrcAlgorithm :: Crc32Iscsi => ( crc32_iscsi_calculator as CalculatorFn , CRC32_ISCSI ) ,
509
560
CrcAlgorithm :: Crc32IsoHdlc => ( crc32_iso_hdlc_calculator as CalculatorFn , CRC32_ISO_HDLC ) ,
510
561
CrcAlgorithm :: Crc32Jamcrc => ( Calculator :: calculate as CalculatorFn , CRC32_JAMCRC ) ,
511
562
CrcAlgorithm :: Crc32Mef => ( Calculator :: calculate as CalculatorFn , CRC32_MEF ) ,
512
563
CrcAlgorithm :: Crc32Mpeg2 => ( Calculator :: calculate as CalculatorFn , CRC32_MPEG_2 ) ,
513
564
CrcAlgorithm :: Crc32Xfer => ( Calculator :: calculate as CalculatorFn , CRC32_XFER ) ,
565
+ CrcAlgorithm :: Crc64Custom => {
566
+ panic ! ( "Custom CRC-64 requires parameters via get_custom_params()" )
567
+ }
514
568
CrcAlgorithm :: Crc64Ecma182 => ( Calculator :: calculate as CalculatorFn , CRC64_ECMA_182 ) ,
515
569
CrcAlgorithm :: Crc64GoIso => ( Calculator :: calculate as CalculatorFn , CRC64_GO_ISO ) ,
516
570
CrcAlgorithm :: Crc64Ms => ( Calculator :: calculate as CalculatorFn , CRC64_MS ) ,
@@ -560,6 +614,7 @@ mod lib {
560
614
use super :: * ;
561
615
use crate :: test:: consts:: { TEST_ALL_CONFIGS , TEST_CHECK_STRING } ;
562
616
use crate :: test:: enums:: AnyCrcTestConfig ;
617
+ use crate :: CrcAlgorithm :: Crc32Iscsi ;
563
618
use cbindgen:: Language :: { Cxx , C } ;
564
619
use cbindgen:: Style :: Both ;
565
620
use rand:: { rng, Rng } ;
@@ -612,6 +667,39 @@ mod lib {
612
667
) ;
613
668
}
614
669
670
+ #[ test]
671
+ fn test_get_custom_params ( ) {
672
+ let custom_crc32 = get_custom_params (
673
+ "Custom CRC-32/ISCSI" ,
674
+ 32 ,
675
+ CRC32_ISCSI . poly ,
676
+ CRC32_ISCSI . init ,
677
+ CRC32_ISCSI . refin ,
678
+ CRC32_ISCSI . xorout ,
679
+ CRC32_ISCSI . check ,
680
+ ) ;
681
+
682
+ assert_eq ! (
683
+ checksum_with_params( custom_crc32, TEST_CHECK_STRING ) ,
684
+ CRC32_ISCSI . check,
685
+ ) ;
686
+
687
+ let custom_crc64 = get_custom_params (
688
+ "Custom CRC-64/NVME" ,
689
+ 64 ,
690
+ CRC64_NVME . poly ,
691
+ CRC64_NVME . init ,
692
+ CRC64_NVME . refin ,
693
+ CRC64_NVME . xorout ,
694
+ CRC64_NVME . check ,
695
+ ) ;
696
+
697
+ assert_eq ! (
698
+ checksum_with_params( custom_crc64, TEST_CHECK_STRING ) ,
699
+ CRC64_NVME . check,
700
+ ) ;
701
+ }
702
+
615
703
#[ test]
616
704
fn test_digest_updates_check ( ) {
617
705
for config in TEST_ALL_CONFIGS {
@@ -720,6 +808,41 @@ mod lib {
720
808
}
721
809
}
722
810
811
+ #[ test]
812
+ fn test_combine_with_custom_params ( ) {
813
+ // CRC-32 reflected
814
+ let checksum1 = checksum_with_params ( CRC32_ISCSI , "1234" . as_ref ( ) ) ;
815
+ let checksum2 = checksum_with_params ( CRC32_ISCSI , "56789" . as_ref ( ) ) ;
816
+ assert_eq ! (
817
+ checksum_combine_with_custom_params( CRC32_ISCSI , checksum1, checksum2, 5 ) ,
818
+ CRC32_ISCSI . check,
819
+ ) ;
820
+
821
+ // CRC-32 forward
822
+ let checksum1 = checksum_with_params ( CRC32_BZIP2 , "1234" . as_ref ( ) ) ;
823
+ let checksum2 = checksum_with_params ( CRC32_BZIP2 , "56789" . as_ref ( ) ) ;
824
+ assert_eq ! (
825
+ checksum_combine_with_custom_params( CRC32_BZIP2 , checksum1, checksum2, 5 ) ,
826
+ CRC32_BZIP2 . check,
827
+ ) ;
828
+
829
+ // CRC-64 reflected
830
+ let checksum1 = checksum_with_params ( CRC64_NVME , "1234" . as_ref ( ) ) ;
831
+ let checksum2 = checksum_with_params ( CRC64_NVME , "56789" . as_ref ( ) ) ;
832
+ assert_eq ! (
833
+ checksum_combine_with_custom_params( CRC64_NVME , checksum1, checksum2, 5 ) ,
834
+ CRC64_NVME . check,
835
+ ) ;
836
+
837
+ // CRC-64 forward
838
+ let checksum1 = checksum_with_params ( CRC64_ECMA_182 , "1234" . as_ref ( ) ) ;
839
+ let checksum2 = checksum_with_params ( CRC64_ECMA_182 , "56789" . as_ref ( ) ) ;
840
+ assert_eq ! (
841
+ checksum_combine_with_custom_params( CRC64_ECMA_182 , checksum1, checksum2, 5 ) ,
842
+ CRC64_ECMA_182 . check,
843
+ ) ;
844
+ }
845
+
723
846
#[ test]
724
847
fn test_checksum_file ( ) {
725
848
// Create a test file with repeating zeros
0 commit comments