Skip to content

Commit 97d8d51

Browse files
committed
Add more custom parameter support
- Crc32Custom and Crc64Custom CrcAlgorithms - checksum_combine_with_custom_params() function - get_custom_params() function - test coverage for the above
1 parent 54779da commit 97d8d51

File tree

2 files changed

+125
-0
lines changed

2 files changed

+125
-0
lines changed

src/enums.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,14 @@ impl Display for CrcAlgorithm {
4343
CrcAlgorithm::Crc32Bzip2 => write!(f, "{}", NAME_CRC32_BZIP2),
4444
CrcAlgorithm::Crc32CdRomEdc => write!(f, "{}", NAME_CRC32_CD_ROM_EDC),
4545
CrcAlgorithm::Crc32Cksum => write!(f, "{}", NAME_CRC32_CKSUM),
46+
CrcAlgorithm::Crc32Custom => write!(f, "CRC-32/CUSTOM"),
4647
CrcAlgorithm::Crc32Iscsi => write!(f, "{}", NAME_CRC32_ISCSI),
4748
CrcAlgorithm::Crc32IsoHdlc => write!(f, "{}", NAME_CRC32_ISO_HDLC),
4849
CrcAlgorithm::Crc32Jamcrc => write!(f, "{}", NAME_CRC32_JAMCRC),
4950
CrcAlgorithm::Crc32Mef => write!(f, "{}", NAME_CRC32_MEF),
5051
CrcAlgorithm::Crc32Mpeg2 => write!(f, "{}", NAME_CRC32_MPEG_2),
5152
CrcAlgorithm::Crc32Xfer => write!(f, "{}", NAME_CRC32_XFER),
53+
CrcAlgorithm::Crc64Custom => write!(f, "CRC-64/CUSTOM"),
5254
CrcAlgorithm::Crc64GoIso => write!(f, "{}", NAME_CRC64_GO_ISO),
5355
CrcAlgorithm::Crc64Ms => write!(f, "{}", NAME_CRC64_MS),
5456
CrcAlgorithm::Crc64Nvme => write!(f, "{}", NAME_CRC64_NVME),

src/lib.rs

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,12 +144,14 @@ pub enum CrcAlgorithm {
144144
Crc32Bzip2,
145145
Crc32CdRomEdc,
146146
Crc32Cksum,
147+
Crc32Custom, // Custom CRC-32 implementation, not defined in consts
147148
Crc32Iscsi,
148149
Crc32IsoHdlc,
149150
Crc32Jamcrc,
150151
Crc32Mef,
151152
Crc32Mpeg2,
152153
Crc32Xfer,
154+
Crc64Custom, // Custom CRC-64 implementation, not defined in consts
153155
Crc64Ecma182,
154156
Crc64GoIso,
155157
Crc64Ms,
@@ -480,6 +482,52 @@ pub fn checksum_combine(
480482
combine::checksums(checksum1, checksum2, checksum2_len, params)
481483
}
482484

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+
483531
/// Returns the target used to calculate the CRC checksum for the specified algorithm.
484532
///
485533
/// 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) {
505553
CrcAlgorithm::Crc32Bzip2 => (Calculator::calculate as CalculatorFn, CRC32_BZIP2),
506554
CrcAlgorithm::Crc32CdRomEdc => (Calculator::calculate as CalculatorFn, CRC32_CD_ROM_EDC),
507555
CrcAlgorithm::Crc32Cksum => (Calculator::calculate as CalculatorFn, CRC32_CKSUM),
556+
CrcAlgorithm::Crc32Custom => {
557+
panic!("Custom CRC-32 requires parameters via get_custom_params()")
558+
}
508559
CrcAlgorithm::Crc32Iscsi => (crc32_iscsi_calculator as CalculatorFn, CRC32_ISCSI),
509560
CrcAlgorithm::Crc32IsoHdlc => (crc32_iso_hdlc_calculator as CalculatorFn, CRC32_ISO_HDLC),
510561
CrcAlgorithm::Crc32Jamcrc => (Calculator::calculate as CalculatorFn, CRC32_JAMCRC),
511562
CrcAlgorithm::Crc32Mef => (Calculator::calculate as CalculatorFn, CRC32_MEF),
512563
CrcAlgorithm::Crc32Mpeg2 => (Calculator::calculate as CalculatorFn, CRC32_MPEG_2),
513564
CrcAlgorithm::Crc32Xfer => (Calculator::calculate as CalculatorFn, CRC32_XFER),
565+
CrcAlgorithm::Crc64Custom => {
566+
panic!("Custom CRC-64 requires parameters via get_custom_params()")
567+
}
514568
CrcAlgorithm::Crc64Ecma182 => (Calculator::calculate as CalculatorFn, CRC64_ECMA_182),
515569
CrcAlgorithm::Crc64GoIso => (Calculator::calculate as CalculatorFn, CRC64_GO_ISO),
516570
CrcAlgorithm::Crc64Ms => (Calculator::calculate as CalculatorFn, CRC64_MS),
@@ -560,6 +614,7 @@ mod lib {
560614
use super::*;
561615
use crate::test::consts::{TEST_ALL_CONFIGS, TEST_CHECK_STRING};
562616
use crate::test::enums::AnyCrcTestConfig;
617+
use crate::CrcAlgorithm::Crc32Iscsi;
563618
use cbindgen::Language::{Cxx, C};
564619
use cbindgen::Style::Both;
565620
use rand::{rng, Rng};
@@ -612,6 +667,39 @@ mod lib {
612667
);
613668
}
614669

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+
615703
#[test]
616704
fn test_digest_updates_check() {
617705
for config in TEST_ALL_CONFIGS {
@@ -720,6 +808,41 @@ mod lib {
720808
}
721809
}
722810

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+
723846
#[test]
724847
fn test_checksum_file() {
725848
// Create a test file with repeating zeros

0 commit comments

Comments
 (0)