Perform CRC calculations from a list of CRC algorithms

Hi. How could you for exemple to calculate various CRC on the same data in a for loop ?

What I have written :

let crc_algos = ["CRC_16_ARC",
"CRC_16_CDMA2000",
"CRC_16_CMS",
"CRC_16_DDS_110",
"CRC_16_DECT_R",
"CRC_16_DECT_X",
"CRC_16_DNP",
"CRC_16_EN_13757"];

for algo_item in crc_algos {
    let mut crc_algo : crc::Crc<u16> = crc::Crc::<u16>::new(&crc::algo_item); // Pickup CRC algo
    let crc_result = crc_algo.checksum(&buffer); // CRC calculation
    println!("algo = {};\tcrc_result = 0x{:02X}", algo_item, crc_result); // Show Result
};

The tedious problem is how to point to crc::constants from a string.

Best regards.

You seem to be already calculating various CRC's over the same data in a for loop?

What OP didn't say is that the given code does not compile because Crc::new takes a &Algorithm, not a string.

From the crc crate docs, it seems like you need to pass in the CRC algorithm constants, not string constants:

Hmm, Ok for array of crc constants. But in the for loop, I get this error of compilation :

129 |     for algo_item in crc_algos {        
    |         --------- binding `algo_item` declared here
130 |         let mut crc_algo : crc::Crc<u16> = crc::Crc::<u16>::new(&algo_item);
    |                                            ---------------------^^^^^^^^^^-
    |                                            |                    |
    |                                            |                    borrowed value does not live long enough
    |                                            argument requires that `algo_item` is borrowed for `'static`
...
133 |     }
    |     - `algo_item` dropped here while still borrowed

try this:

let crc_algos = [&crc::CRC_16_ARC,
        &crc::CRC_16_CDMA2000,
    ];

for algo_item in crc_algos {
        let mut crc_algo : crc::Crc<u16> = crc::Crc::<u16>::new(algo_item); // Pickup CRC algo
        let crc_result = crc_algo.checksum(&buffer); // CRC calculation
        println!("crc_result = 0x{:02X}",  crc_result); // Show Result
    };

1 Like

In my side, I nearly found nearly same code as you :

let crc_algos = &[crc::CRC_16_ARC, crc::CRC_16_CDMA2000];

for algo_item in crc_algos {    		
		let crc_algo : crc::Crc<u16> = crc::Crc::<u16>::new(algo_item);
		let crc_result = crc_algo.checksum(&buffer);
		println!("algo = {};\tcrc_result = 0x{:02X}", stringify!(algo_item), crc_result);
	}

but for println!() I got :

algo = algo_item;       crc_result = 0x00
algo = algo_item;       crc_result = 0xF1F3

I expect :
algo = crc::CRC_16_ARC; crc_result = 0x00
algo = crc::CRC_16_CDMA2000; crc_result = 0xF1F3

stringify! operates on the literal tokens you give it.

Since crc::Algorithm doesn't implement Debug (and even if it did, it'd give you Algorithm { width: ... poly: ... etc.}) you need to handle the debug printing yourself.

Unfortunately, this basically becomes no easier than this:

You can craft a macro to reduce the repetition, but there no built-in way that I know of to debug print the constant names used to build a list.

1 Like

So. I'll make 2 arrays (one with constant strings, other with associated crc::constants) or maybe an array of struct {constant_name, crc::constant}.
Thanks for your enlightenment.

Yes. e.g.:

use crc::{
    Algorithm, CRC_16_ARC, CRC_16_CDMA2000, CRC_16_CMS, CRC_16_DDS_110, CRC_16_DECT_R,
    CRC_16_DECT_X, CRC_16_DNP, CRC_16_EN_13757, Crc,
};

const CRC_ALGORITHMS: [(&str, Algorithm<u16>); 8] = [
    ("CRC_16_ARC", CRC_16_ARC),
    ("CRC_16_CDMA2000", CRC_16_CDMA2000),
    ("CRC_16_CMS", CRC_16_CMS),
    ("CRC_16_DDS_110", CRC_16_DDS_110),
    ("CRC_16_DECT_R", CRC_16_DECT_R),
    ("CRC_16_DECT_X", CRC_16_DECT_X),
    ("CRC_16_DNP", CRC_16_DNP),
    ("CRC_16_EN_13757", CRC_16_EN_13757),
];

fn main() {
    let buffer: [u8; 0] = [];

    for (name, algorithm) in &CRC_ALGORITHMS {
        let crc_result = Crc::<u16>::new(algorithm).checksum(&buffer);
        println!("algo = {name};\tcrc_result = 0x{:02X}", crc_result);
    }
}

resulting in

algo = CRC_16_ARC;	crc_result = 0x00
algo = CRC_16_CDMA2000;	crc_result = 0xFFFF
algo = CRC_16_CMS;	crc_result = 0xFFFF
algo = CRC_16_DDS_110;	crc_result = 0x800D
algo = CRC_16_DECT_R;	crc_result = 0x01
algo = CRC_16_DECT_X;	crc_result = 0x00
algo = CRC_16_DNP;	crc_result = 0xFFFF
algo = CRC_16_EN_13757;	crc_result = 0xFFFF
2 Likes

With extracting a list of crc algos that give the good crc. (Because CRC get probable collisions)

use crc::{
    Algorithm, CRC_16_ARC, CRC_16_CDMA2000, CRC_16_CMS, CRC_16_DDS_110, CRC_16_DECT_R,
    CRC_16_DECT_X, CRC_16_DNP, CRC_16_EN_13757, Crc,
};

const CRC_ALGORITHMS: [(&str, Algorithm<u16>); 8] = [
    ("CRC_16_ARC", CRC_16_ARC),
    ("CRC_16_CDMA2000", CRC_16_CDMA2000),
    ("CRC_16_CMS", CRC_16_CMS),
    ("CRC_16_DDS_110", CRC_16_DDS_110),
    ("CRC_16_DECT_R", CRC_16_DECT_R),
    ("CRC_16_DECT_X", CRC_16_DECT_X),
    ("CRC_16_DNP", CRC_16_DNP),
    ("CRC_16_EN_13757", CRC_16_EN_13757),
];

fn main() {
    let buffer: [u8; 0] = [];

    let crc_given :u16 = 0x0000; // expected crc
    let mut right_algo = vec!(); // array of algo names that give the same crc_result
   
    for (name, algorithm) in &CRC_ALGORITHMS {
        let crc_result = Crc::<u16>::new(algorithm).checksum(&buffer);
        println!("algo = {name};\tcrc_result = 0x{:04X}", crc_result);
		if crc_result == crc_given { 
			println!("^^^^^^^^^^^^^^^^^^      This one seems to be the right crc algo.");
			right_algo.push(name); // append matched crc algo to list of right algos
		}
    }
    println!("right algos = {:?}", right_algo);

}