1use crate::compiler::function::EnumVariant;
2use crate::compiler::prelude::*;
3use crc::Crc as CrcInstance;
4use std::sync::LazyLock;
5
6static DEFAULT_ALGORITHM: LazyLock<Value> =
7 LazyLock::new(|| Value::Bytes(Bytes::from("CRC_32_ISO_HDLC")));
8
9const VALID_ALGORITHMS: &[&str] = &[
10 "CRC_3_GSM",
11 "CRC_3_ROHC",
12 "CRC_4_G_704",
13 "CRC_4_INTERLAKEN",
14 "CRC_5_EPC_C1G2",
15 "CRC_5_G_704",
16 "CRC_5_USB",
17 "CRC_6_CDMA2000_A",
18 "CRC_6_CDMA2000_B",
19 "CRC_6_DARC",
20 "CRC_6_GSM",
21 "CRC_6_G_704",
22 "CRC_7_MMC",
23 "CRC_7_ROHC",
24 "CRC_7_UMTS",
25 "CRC_8_AUTOSAR",
26 "CRC_8_BLUETOOTH",
27 "CRC_8_CDMA2000",
28 "CRC_8_DARC",
29 "CRC_8_DVB_S2",
30 "CRC_8_GSM_A",
31 "CRC_8_GSM_B",
32 "CRC_8_HITAG",
33 "CRC_8_I_432_1",
34 "CRC_8_I_CODE",
35 "CRC_8_LTE",
36 "CRC_8_MAXIM_DOW",
37 "CRC_8_MIFARE_MAD",
38 "CRC_8_NRSC_5",
39 "CRC_8_OPENSAFETY",
40 "CRC_8_ROHC",
41 "CRC_8_SAE_J1850",
42 "CRC_8_SMBUS",
43 "CRC_8_TECH_3250",
44 "CRC_8_WCDMA",
45 "CRC_10_ATM",
46 "CRC_10_CDMA2000",
47 "CRC_10_GSM",
48 "CRC_11_FLEXRAY",
49 "CRC_11_UMTS",
50 "CRC_12_CDMA2000",
51 "CRC_12_DECT",
52 "CRC_12_GSM",
53 "CRC_12_UMTS",
54 "CRC_13_BBC",
55 "CRC_14_DARC",
56 "CRC_14_GSM",
57 "CRC_15_CAN",
58 "CRC_15_MPT1327",
59 "CRC_16_ARC",
60 "CRC_16_CDMA2000",
61 "CRC_16_CMS",
62 "CRC_16_DDS_110",
63 "CRC_16_DECT_R",
64 "CRC_16_DECT_X",
65 "CRC_16_DNP",
66 "CRC_16_EN_13757",
67 "CRC_16_GENIBUS",
68 "CRC_16_GSM",
69 "CRC_16_IBM_3740",
70 "CRC_16_IBM_SDLC",
71 "CRC_16_ISO_IEC_14443_3_A",
72 "CRC_16_KERMIT",
73 "CRC_16_LJ1200",
74 "CRC_16_M17",
75 "CRC_16_MAXIM_DOW",
76 "CRC_16_MCRF4XX",
77 "CRC_16_MODBUS",
78 "CRC_16_NRSC_5",
79 "CRC_16_OPENSAFETY_A",
80 "CRC_16_OPENSAFETY_B",
81 "CRC_16_PROFIBUS",
82 "CRC_16_RIELLO",
83 "CRC_16_SPI_FUJITSU",
84 "CRC_16_T10_DIF",
85 "CRC_16_TELEDISK",
86 "CRC_16_TMS37157",
87 "CRC_16_UMTS",
88 "CRC_16_USB",
89 "CRC_16_XMODEM",
90 "CRC_17_CAN_FD",
91 "CRC_21_CAN_FD",
92 "CRC_24_BLE",
93 "CRC_24_FLEXRAY_A",
94 "CRC_24_FLEXRAY_B",
95 "CRC_24_INTERLAKEN",
96 "CRC_24_LTE_A",
97 "CRC_24_LTE_B",
98 "CRC_24_OPENPGP",
99 "CRC_24_OS_9",
100 "CRC_30_CDMA",
101 "CRC_31_PHILIPS",
102 "CRC_32_AIXM",
103 "CRC_32_AUTOSAR",
104 "CRC_32_BASE91_D",
105 "CRC_32_BZIP2",
106 "CRC_32_CD_ROM_EDC",
107 "CRC_32_CKSUM",
108 "CRC_32_ISCSI",
109 "CRC_32_ISO_HDLC",
110 "CRC_32_JAMCRC",
111 "CRC_32_MEF",
112 "CRC_32_MPEG_2",
113 "CRC_32_XFER",
114 "CRC_40_GSM",
115 "CRC_64_ECMA_182",
116 "CRC_64_GO_ISO",
117 "CRC_64_MS",
118 "CRC_64_REDIS",
119 "CRC_64_WE",
120 "CRC_64_XZ",
121 "CRC_82_DARC",
122];
123
124static ALGORITHM_ENUM: &[EnumVariant] = &[
125 EnumVariant {
126 value: "CRC_3_GSM",
127 description: "3-bit CRC used in GSM telecommunications for error detection",
128 },
129 EnumVariant {
130 value: "CRC_3_ROHC",
131 description: "3-bit CRC used in Robust Header Compression (ROHC) protocol",
132 },
133 EnumVariant {
134 value: "CRC_4_G_704",
135 description: "4-bit CRC specified in ITU-T G.704 for synchronous communication systems",
136 },
137 EnumVariant {
138 value: "CRC_4_INTERLAKEN",
139 description: "4-bit CRC used in Interlaken high-speed serial communication protocol",
140 },
141 EnumVariant {
142 value: "CRC_5_EPC_C1G2",
143 description: "5-bit CRC used in EPC Gen 2 RFID (Radio-Frequency Identification) standard",
144 },
145 EnumVariant {
146 value: "CRC_5_G_704",
147 description: "5-bit CRC variant in ITU-T G.704 telecommunication standard",
148 },
149 EnumVariant {
150 value: "CRC_5_USB",
151 description: "5-bit CRC used in USB communication for detecting transmission errors",
152 },
153 EnumVariant {
154 value: "CRC_6_CDMA2000_A",
155 description: "6-bit CRC variant used in CDMA2000 network protocols",
156 },
157 EnumVariant {
158 value: "CRC_6_CDMA2000_B",
159 description: "Alternative 6-bit CRC variant for CDMA2000 network protocols",
160 },
161 EnumVariant {
162 value: "CRC_6_DARC",
163 description: "6-bit CRC used in DARC (Digital Audio Radio Channel) communication",
164 },
165 EnumVariant {
166 value: "CRC_6_GSM",
167 description: "6-bit CRC variant used in GSM telecommunications",
168 },
169 EnumVariant {
170 value: "CRC_6_G_704",
171 description: "6-bit CRC specified in ITU-T G.704 for synchronous communication",
172 },
173 EnumVariant {
174 value: "CRC_7_MMC",
175 description: "7-bit CRC used in MultiMediaCard (MMC) storage systems for error detection",
176 },
177 EnumVariant {
178 value: "CRC_7_ROHC",
179 description: "7-bit CRC used in Robust Header Compression (ROHC) protocol",
180 },
181 EnumVariant {
182 value: "CRC_7_UMTS",
183 description: "7-bit CRC used in UMTS (Universal Mobile Telecommunications System)",
184 },
185 EnumVariant {
186 value: "CRC_8_AUTOSAR",
187 description: "8-bit CRC used in AUTOSAR (Automotive Open System Architecture) standard",
188 },
189 EnumVariant {
190 value: "CRC_8_BLUETOOTH",
191 description: "8-bit CRC polynomial used in Bluetooth communication protocols",
192 },
193 EnumVariant {
194 value: "CRC_8_CDMA2000",
195 description: "8-bit CRC used in CDMA2000 cellular communication standard",
196 },
197 EnumVariant {
198 value: "CRC_8_DARC",
199 description: "8-bit CRC used in DARC (Digital Audio Radio Channel) communication",
200 },
201 EnumVariant {
202 value: "CRC_8_DVB_S2",
203 description: "8-bit CRC used in DVB-S2 (Digital Video Broadcasting Satellite Second Generation)",
204 },
205 EnumVariant {
206 value: "CRC_8_GSM_A",
207 description: "8-bit CRC variant A used in GSM telecommunications",
208 },
209 EnumVariant {
210 value: "CRC_8_GSM_B",
211 description: "8-bit CRC variant B used in GSM telecommunications",
212 },
213 EnumVariant {
214 value: "CRC_8_HITAG",
215 description: "8-bit CRC used in Hitag RFID and transponder systems",
216 },
217 EnumVariant {
218 value: "CRC_8_I_432_1",
219 description: "8-bit CRC specified in IEEE 1432.1 standard",
220 },
221 EnumVariant {
222 value: "CRC_8_I_CODE",
223 description: "8-bit CRC used in I-CODE RFID systems",
224 },
225 EnumVariant {
226 value: "CRC_8_LTE",
227 description: "8-bit CRC used in LTE (Long-Term Evolution) cellular networks",
228 },
229 EnumVariant {
230 value: "CRC_8_MAXIM_DOW",
231 description: "8-bit CRC used by Maxim/Dallas Semiconductor for 1-Wire and iButton devices",
232 },
233 EnumVariant {
234 value: "CRC_8_MIFARE_MAD",
235 description: "8-bit CRC used in MIFARE MAD (Multiple Application Directory) protocol",
236 },
237 EnumVariant {
238 value: "CRC_8_NRSC_5",
239 description: "8-bit CRC used in NRSC-5 digital radio broadcasting standard",
240 },
241 EnumVariant {
242 value: "CRC_8_OPENSAFETY",
243 description: "8-bit CRC used in OpenSAFETY industrial communication protocol",
244 },
245 EnumVariant {
246 value: "CRC_8_ROHC",
247 description: "8-bit CRC used in Robust Header Compression (ROHC) protocol",
248 },
249 EnumVariant {
250 value: "CRC_8_SAE_J1850",
251 description: "8-bit CRC used in SAE J1850 automotive communication protocol",
252 },
253 EnumVariant {
254 value: "CRC_8_SMBUS",
255 description: "8-bit CRC used in System Management Bus (SMBus) communication",
256 },
257 EnumVariant {
258 value: "CRC_8_TECH_3250",
259 description: "8-bit CRC used in SMPTE (Society of Motion Picture and Television Engineers) standard",
260 },
261 EnumVariant {
262 value: "CRC_8_WCDMA",
263 description: "8-bit CRC used in WCDMA (Wideband Code Division Multiple Access) networks",
264 },
265 EnumVariant {
266 value: "CRC_10_ATM",
267 description: "10-bit CRC used in ATM (Asynchronous Transfer Mode) cell headers",
268 },
269 EnumVariant {
270 value: "CRC_10_CDMA2000",
271 description: "10-bit CRC used in CDMA2000 cellular communication standard",
272 },
273 EnumVariant {
274 value: "CRC_10_GSM",
275 description: "10-bit CRC variant used in GSM telecommunications",
276 },
277 EnumVariant {
278 value: "CRC_11_FLEXRAY",
279 description: "11-bit CRC used in FlexRay automotive communication protocol",
280 },
281 EnumVariant {
282 value: "CRC_11_UMTS",
283 description: "11-bit CRC used in UMTS (Universal Mobile Telecommunications System)",
284 },
285 EnumVariant {
286 value: "CRC_12_CDMA2000",
287 description: "12-bit CRC used in CDMA2000 cellular communication standard",
288 },
289 EnumVariant {
290 value: "CRC_12_DECT",
291 description: "12-bit CRC used in DECT (Digital Enhanced Cordless Telecommunications) standards",
292 },
293 EnumVariant {
294 value: "CRC_12_GSM",
295 description: "12-bit CRC variant used in GSM telecommunications",
296 },
297 EnumVariant {
298 value: "CRC_12_UMTS",
299 description: "12-bit CRC used in UMTS (Universal Mobile Telecommunications System)",
300 },
301 EnumVariant {
302 value: "CRC_13_BBC",
303 description: "13-bit CRC used in BBC (British Broadcasting Corporation) digital transmission",
304 },
305 EnumVariant {
306 value: "CRC_14_DARC",
307 description: "14-bit CRC used in DARC (Digital Audio Radio Channel) communication",
308 },
309 EnumVariant {
310 value: "CRC_14_GSM",
311 description: "14-bit CRC variant used in GSM telecommunications",
312 },
313 EnumVariant {
314 value: "CRC_15_CAN",
315 description: "15-bit CRC used in CAN (Controller Area Network) automotive communication",
316 },
317 EnumVariant {
318 value: "CRC_15_MPT1327",
319 description: "15-bit CRC used in MPT 1327 radio trunking system",
320 },
321 EnumVariant {
322 value: "CRC_16_ARC",
323 description: "16-bit CRC used in ARC (Adaptive Routing Code) communication",
324 },
325 EnumVariant {
326 value: "CRC_16_CDMA2000",
327 description: "16-bit CRC used in CDMA2000 cellular communication standard",
328 },
329 EnumVariant {
330 value: "CRC_16_CMS",
331 description: "16-bit CRC used in Content Management Systems for data integrity",
332 },
333 EnumVariant {
334 value: "CRC_16_DDS_110",
335 description: "16-bit CRC used in DDS (Digital Data Storage) standard",
336 },
337 EnumVariant {
338 value: "CRC_16_DECT_R",
339 description: "16-bit CRC variant R used in DECT communication",
340 },
341 EnumVariant {
342 value: "CRC_16_DECT_X",
343 description: "16-bit CRC variant X used in DECT communication",
344 },
345 EnumVariant {
346 value: "CRC_16_DNP",
347 description: "16-bit CRC used in DNP3 (Distributed Network Protocol) for utilities",
348 },
349 EnumVariant {
350 value: "CRC_16_EN_13757",
351 description: "16-bit CRC specified in EN 13757 for meter communication",
352 },
353 EnumVariant {
354 value: "CRC_16_GENIBUS",
355 description: "16-bit CRC used in GENIBUS communication protocol",
356 },
357 EnumVariant {
358 value: "CRC_16_GSM",
359 description: "16-bit CRC variant used in GSM telecommunications",
360 },
361 EnumVariant {
362 value: "CRC_16_IBM_3740",
363 description: "16-bit CRC used in IBM 3740 data integrity checks",
364 },
365 EnumVariant {
366 value: "CRC_16_IBM_SDLC",
367 description: "16-bit CRC used in IBM SDLC (Synchronous Data Link Control)",
368 },
369 EnumVariant {
370 value: "CRC_16_ISO_IEC_14443_3_A",
371 description: "16-bit CRC used in ISO/IEC 14443-3 Type A contactless smart cards",
372 },
373 EnumVariant {
374 value: "CRC_16_KERMIT",
375 description: "16-bit CRC used in Kermit file transfer protocol",
376 },
377 EnumVariant {
378 value: "CRC_16_LJ1200",
379 description: "16-bit CRC used in LJ1200 communication system",
380 },
381 EnumVariant {
382 value: "CRC_16_M17",
383 description: "16-bit CRC used in M17 digital radio communication",
384 },
385 EnumVariant {
386 value: "CRC_16_MAXIM_DOW",
387 description: "16-bit CRC used by Maxim/Dallas Semiconductor for data integrity",
388 },
389 EnumVariant {
390 value: "CRC_16_MCRF4XX",
391 description: "16-bit CRC used in MCRF4XX RFID systems",
392 },
393 EnumVariant {
394 value: "CRC_16_MODBUS",
395 description: "16-bit CRC used in Modbus communication protocol for error detection",
396 },
397 EnumVariant {
398 value: "CRC_16_NRSC_5",
399 description: "16-bit CRC used in NRSC-5 digital radio broadcasting standard",
400 },
401 EnumVariant {
402 value: "CRC_16_OPENSAFETY_A",
403 description: "16-bit CRC variant A in OpenSAFETY industrial communication",
404 },
405 EnumVariant {
406 value: "CRC_16_OPENSAFETY_B",
407 description: "16-bit CRC variant B in OpenSAFETY industrial communication",
408 },
409 EnumVariant {
410 value: "CRC_16_PROFIBUS",
411 description: "16-bit CRC used in PROFIBUS industrial communication protocol",
412 },
413 EnumVariant {
414 value: "CRC_16_RIELLO",
415 description: "16-bit CRC used in Riello UPS communication",
416 },
417 EnumVariant {
418 value: "CRC_16_SPI_FUJITSU",
419 description: "16-bit CRC used in Fujitsu SPI (Serial Peripheral Interface) communication",
420 },
421 EnumVariant {
422 value: "CRC_16_T10_DIF",
423 description: "16-bit CRC used in T10 DIF (Data Integrity Field) standard",
424 },
425 EnumVariant {
426 value: "CRC_16_TELEDISK",
427 description: "16-bit CRC used in Teledisk disk image format",
428 },
429 EnumVariant {
430 value: "CRC_16_TMS37157",
431 description: "16-bit CRC used in TMS37157 microcontroller communication",
432 },
433 EnumVariant {
434 value: "CRC_16_UMTS",
435 description: "16-bit CRC used in UMTS (Universal Mobile Telecommunications System)",
436 },
437 EnumVariant {
438 value: "CRC_16_USB",
439 description: "16-bit CRC used in USB communication for error detection",
440 },
441 EnumVariant {
442 value: "CRC_16_XMODEM",
443 description: "16-bit CRC used in XMODEM file transfer protocol",
444 },
445 EnumVariant {
446 value: "CRC_17_CAN_FD",
447 description: "17-bit CRC used in CAN FD (Flexible Data-Rate) automotive communication protocol",
448 },
449 EnumVariant {
450 value: "CRC_21_CAN_FD",
451 description: "21-bit CRC variant used in CAN FD (Flexible Data-Rate) automotive communication",
452 },
453 EnumVariant {
454 value: "CRC_24_BLE",
455 description: "24-bit CRC used in Bluetooth Low Energy (BLE) packet error checking",
456 },
457 EnumVariant {
458 value: "CRC_24_FLEXRAY_A",
459 description: "24-bit CRC variant A used in FlexRay automotive communication protocol",
460 },
461 EnumVariant {
462 value: "CRC_24_FLEXRAY_B",
463 description: "24-bit CRC variant B used in FlexRay automotive communication protocol",
464 },
465 EnumVariant {
466 value: "CRC_24_INTERLAKEN",
467 description: "24-bit CRC used in Interlaken high-speed serial communication protocol",
468 },
469 EnumVariant {
470 value: "CRC_24_LTE_A",
471 description: "24-bit CRC variant A used in LTE (Long-Term Evolution) cellular networks",
472 },
473 EnumVariant {
474 value: "CRC_24_LTE_B",
475 description: "24-bit CRC variant B used in LTE (Long-Term Evolution) cellular networks",
476 },
477 EnumVariant {
478 value: "CRC_24_OPENPGP",
479 description: "24-bit CRC used in OpenPGP (Pretty Good Privacy) for data integrity",
480 },
481 EnumVariant {
482 value: "CRC_24_OS_9",
483 description: "24-bit CRC used in OS-9 operating system for error detection",
484 },
485 EnumVariant {
486 value: "CRC_30_CDMA",
487 description: "30-bit CRC used in CDMA (Code Division Multiple Access) communication standard",
488 },
489 EnumVariant {
490 value: "CRC_31_PHILIPS",
491 description: "31-bit CRC used in Philips communication protocols",
492 },
493 EnumVariant {
494 value: "CRC_32_AIXM",
495 description: "32-bit CRC used in Aeronautical Information Exchange Model (AIXM)",
496 },
497 EnumVariant {
498 value: "CRC_32_AUTOSAR",
499 description: "32-bit CRC used in AUTOSAR (Automotive Open System Architecture) standard",
500 },
501 EnumVariant {
502 value: "CRC_32_BASE91_D",
503 description: "32-bit CRC variant used in Base91 data encoding",
504 },
505 EnumVariant {
506 value: "CRC_32_BZIP2",
507 description: "32-bit CRC used in bzip2 compression algorithm",
508 },
509 EnumVariant {
510 value: "CRC_32_CD_ROM_EDC",
511 description: "32-bit CRC used for Error Detection Code in CD-ROM systems",
512 },
513 EnumVariant {
514 value: "CRC_32_CKSUM",
515 description: "32-bit CRC used in UNIX cksum command for file integrity",
516 },
517 EnumVariant {
518 value: "CRC_32_ISCSI",
519 description: "32-bit CRC used in iSCSI (Internet Small Computer Systems Interface)",
520 },
521 EnumVariant {
522 value: "CRC_32_ISO_HDLC",
523 description: "32-bit CRC used in ISO HDLC (High-Level Data Link Control)",
524 },
525 EnumVariant {
526 value: "CRC_32_JAMCRC",
527 description: "32-bit CRC variant used in JAM error detection",
528 },
529 EnumVariant {
530 value: "CRC_32_MEF",
531 description: "32-bit CRC used in Metro Ethernet Forum (MEF) standards",
532 },
533 EnumVariant {
534 value: "CRC_32_MPEG_2",
535 description: "32-bit CRC used in MPEG-2 transport streams for error detection",
536 },
537 EnumVariant {
538 value: "CRC_32_XFER",
539 description: "32-bit CRC used in data transfer protocols",
540 },
541 EnumVariant {
542 value: "CRC_40_GSM",
543 description: "40-bit CRC variant used in GSM telecommunications",
544 },
545 EnumVariant {
546 value: "CRC_64_ECMA_182",
547 description: "64-bit CRC specified in ECMA-182 standard",
548 },
549 EnumVariant {
550 value: "CRC_64_GO_ISO",
551 description: "64-bit CRC used in Go programming language and ISO standards",
552 },
553 EnumVariant {
554 value: "CRC_64_MS",
555 description: "64-bit CRC variant used in Microsoft systems",
556 },
557 EnumVariant {
558 value: "CRC_64_REDIS",
559 description: "64-bit CRC used in Redis key-value data store",
560 },
561 EnumVariant {
562 value: "CRC_64_WE",
563 description: "64-bit CRC variant for wide-area error detection",
564 },
565 EnumVariant {
566 value: "CRC_64_XZ",
567 description: "64-bit CRC used in the XZ compression format for integrity verification",
568 },
569 EnumVariant {
570 value: "CRC_82_DARC",
571 description: "82-bit CRC used in DARC (Digital Audio Radio Channel) communication",
572 },
573];
574
575static PARAMETERS: LazyLock<Vec<Parameter>> = LazyLock::new(|| {
576 vec![
577 Parameter::required(
578 "value",
579 kind::BYTES,
580 "The string to calculate the checksum for.",
581 ),
582 Parameter::optional("algorithm", kind::BYTES, "The CRC algorithm to use.")
583 .default(&DEFAULT_ALGORITHM)
584 .enum_variants(ALGORITHM_ENUM),
585 ]
586});
587
588#[allow(clippy::too_many_lines)]
589fn crc(value: Value, algorithm: &str) -> Resolved {
590 let value = value.try_bytes()?;
591
592 let checksum = match algorithm {
593 "CRC_3_GSM" => CrcInstance::<u8>::new(&crc::CRC_3_GSM)
594 .checksum(&value)
595 .to_string(),
596 "CRC_3_ROHC" => CrcInstance::<u8>::new(&crc::CRC_3_ROHC)
597 .checksum(&value)
598 .to_string(),
599 "CRC_4_G_704" => CrcInstance::<u8>::new(&crc::CRC_4_G_704)
600 .checksum(&value)
601 .to_string(),
602 "CRC_4_INTERLAKEN" => CrcInstance::<u8>::new(&crc::CRC_4_INTERLAKEN)
603 .checksum(&value)
604 .to_string(),
605 "CRC_5_EPC_C1G2" => CrcInstance::<u8>::new(&crc::CRC_5_EPC_C1G2)
606 .checksum(&value)
607 .to_string(),
608 "CRC_5_G_704" => CrcInstance::<u8>::new(&crc::CRC_5_G_704)
609 .checksum(&value)
610 .to_string(),
611 "CRC_5_USB" => CrcInstance::<u8>::new(&crc::CRC_5_USB)
612 .checksum(&value)
613 .to_string(),
614 "CRC_6_CDMA2000_A" => CrcInstance::<u8>::new(&crc::CRC_6_CDMA2000_A)
615 .checksum(&value)
616 .to_string(),
617 "CRC_6_CDMA2000_B" => CrcInstance::<u8>::new(&crc::CRC_6_CDMA2000_B)
618 .checksum(&value)
619 .to_string(),
620 "CRC_6_DARC" => CrcInstance::<u8>::new(&crc::CRC_6_DARC)
621 .checksum(&value)
622 .to_string(),
623 "CRC_6_GSM" => CrcInstance::<u8>::new(&crc::CRC_6_GSM)
624 .checksum(&value)
625 .to_string(),
626 "CRC_6_G_704" => CrcInstance::<u8>::new(&crc::CRC_6_G_704)
627 .checksum(&value)
628 .to_string(),
629 "CRC_7_MMC" => CrcInstance::<u8>::new(&crc::CRC_7_MMC)
630 .checksum(&value)
631 .to_string(),
632 "CRC_7_ROHC" => CrcInstance::<u8>::new(&crc::CRC_7_ROHC)
633 .checksum(&value)
634 .to_string(),
635 "CRC_7_UMTS" => CrcInstance::<u8>::new(&crc::CRC_7_UMTS)
636 .checksum(&value)
637 .to_string(),
638 "CRC_8_AUTOSAR" => CrcInstance::<u8>::new(&crc::CRC_8_AUTOSAR)
639 .checksum(&value)
640 .to_string(),
641 "CRC_8_BLUETOOTH" => CrcInstance::<u8>::new(&crc::CRC_8_BLUETOOTH)
642 .checksum(&value)
643 .to_string(),
644 "CRC_8_CDMA2000" => CrcInstance::<u8>::new(&crc::CRC_8_CDMA2000)
645 .checksum(&value)
646 .to_string(),
647 "CRC_8_DARC" => CrcInstance::<u8>::new(&crc::CRC_8_DARC)
648 .checksum(&value)
649 .to_string(),
650 "CRC_8_DVB_S2" => CrcInstance::<u8>::new(&crc::CRC_8_DVB_S2)
651 .checksum(&value)
652 .to_string(),
653 "CRC_8_GSM_A" => CrcInstance::<u8>::new(&crc::CRC_8_GSM_A)
654 .checksum(&value)
655 .to_string(),
656 "CRC_8_GSM_B" => CrcInstance::<u8>::new(&crc::CRC_8_GSM_B)
657 .checksum(&value)
658 .to_string(),
659 "CRC_8_HITAG" => CrcInstance::<u8>::new(&crc::CRC_8_HITAG)
660 .checksum(&value)
661 .to_string(),
662 "CRC_8_I_432_1" => CrcInstance::<u8>::new(&crc::CRC_8_I_432_1)
663 .checksum(&value)
664 .to_string(),
665 "CRC_8_I_CODE" => CrcInstance::<u8>::new(&crc::CRC_8_I_CODE)
666 .checksum(&value)
667 .to_string(),
668 "CRC_8_LTE" => CrcInstance::<u8>::new(&crc::CRC_8_LTE)
669 .checksum(&value)
670 .to_string(),
671 "CRC_8_MAXIM_DOW" => CrcInstance::<u8>::new(&crc::CRC_8_MAXIM_DOW)
672 .checksum(&value)
673 .to_string(),
674 "CRC_8_MIFARE_MAD" => CrcInstance::<u8>::new(&crc::CRC_8_MIFARE_MAD)
675 .checksum(&value)
676 .to_string(),
677 "CRC_8_NRSC_5" => CrcInstance::<u8>::new(&crc::CRC_8_NRSC_5)
678 .checksum(&value)
679 .to_string(),
680 "CRC_8_OPENSAFETY" => CrcInstance::<u8>::new(&crc::CRC_8_OPENSAFETY)
681 .checksum(&value)
682 .to_string(),
683 "CRC_8_ROHC" => CrcInstance::<u8>::new(&crc::CRC_8_ROHC)
684 .checksum(&value)
685 .to_string(),
686 "CRC_8_SAE_J1850" => CrcInstance::<u8>::new(&crc::CRC_8_SAE_J1850)
687 .checksum(&value)
688 .to_string(),
689 "CRC_8_SMBUS" => CrcInstance::<u8>::new(&crc::CRC_8_SMBUS)
690 .checksum(&value)
691 .to_string(),
692 "CRC_8_TECH_3250" => CrcInstance::<u8>::new(&crc::CRC_8_TECH_3250)
693 .checksum(&value)
694 .to_string(),
695 "CRC_8_WCDMA" => CrcInstance::<u8>::new(&crc::CRC_8_WCDMA)
696 .checksum(&value)
697 .to_string(),
698 "CRC_10_ATM" => CrcInstance::<u16>::new(&crc::CRC_10_ATM)
699 .checksum(&value)
700 .to_string(),
701 "CRC_10_CDMA2000" => CrcInstance::<u16>::new(&crc::CRC_10_CDMA2000)
702 .checksum(&value)
703 .to_string(),
704 "CRC_10_GSM" => CrcInstance::<u16>::new(&crc::CRC_10_GSM)
705 .checksum(&value)
706 .to_string(),
707 "CRC_11_FLEXRAY" => CrcInstance::<u16>::new(&crc::CRC_11_FLEXRAY)
708 .checksum(&value)
709 .to_string(),
710 "CRC_11_UMTS" => CrcInstance::<u16>::new(&crc::CRC_11_UMTS)
711 .checksum(&value)
712 .to_string(),
713 "CRC_12_CDMA2000" => CrcInstance::<u16>::new(&crc::CRC_12_CDMA2000)
714 .checksum(&value)
715 .to_string(),
716 "CRC_12_DECT" => CrcInstance::<u16>::new(&crc::CRC_12_DECT)
717 .checksum(&value)
718 .to_string(),
719 "CRC_12_GSM" => CrcInstance::<u16>::new(&crc::CRC_12_GSM)
720 .checksum(&value)
721 .to_string(),
722 "CRC_12_UMTS" => CrcInstance::<u16>::new(&crc::CRC_12_UMTS)
723 .checksum(&value)
724 .to_string(),
725 "CRC_13_BBC" => CrcInstance::<u16>::new(&crc::CRC_13_BBC)
726 .checksum(&value)
727 .to_string(),
728 "CRC_14_DARC" => CrcInstance::<u16>::new(&crc::CRC_14_DARC)
729 .checksum(&value)
730 .to_string(),
731 "CRC_14_GSM" => CrcInstance::<u16>::new(&crc::CRC_14_GSM)
732 .checksum(&value)
733 .to_string(),
734 "CRC_15_CAN" => CrcInstance::<u16>::new(&crc::CRC_15_CAN)
735 .checksum(&value)
736 .to_string(),
737 "CRC_15_MPT1327" => CrcInstance::<u16>::new(&crc::CRC_15_MPT1327)
738 .checksum(&value)
739 .to_string(),
740 "CRC_16_ARC" => CrcInstance::<u16>::new(&crc::CRC_16_ARC)
741 .checksum(&value)
742 .to_string(),
743 "CRC_16_CDMA2000" => CrcInstance::<u16>::new(&crc::CRC_16_CDMA2000)
744 .checksum(&value)
745 .to_string(),
746 "CRC_16_CMS" => CrcInstance::<u16>::new(&crc::CRC_16_CMS)
747 .checksum(&value)
748 .to_string(),
749 "CRC_16_DDS_110" => CrcInstance::<u16>::new(&crc::CRC_16_DDS_110)
750 .checksum(&value)
751 .to_string(),
752 "CRC_16_DECT_R" => CrcInstance::<u16>::new(&crc::CRC_16_DECT_R)
753 .checksum(&value)
754 .to_string(),
755 "CRC_16_DECT_X" => CrcInstance::<u16>::new(&crc::CRC_16_DECT_X)
756 .checksum(&value)
757 .to_string(),
758 "CRC_16_DNP" => CrcInstance::<u16>::new(&crc::CRC_16_DNP)
759 .checksum(&value)
760 .to_string(),
761 "CRC_16_EN_13757" => CrcInstance::<u16>::new(&crc::CRC_16_EN_13757)
762 .checksum(&value)
763 .to_string(),
764 "CRC_16_GENIBUS" => CrcInstance::<u16>::new(&crc::CRC_16_GENIBUS)
765 .checksum(&value)
766 .to_string(),
767 "CRC_16_GSM" => CrcInstance::<u16>::new(&crc::CRC_16_GSM)
768 .checksum(&value)
769 .to_string(),
770 "CRC_16_IBM_3740" => CrcInstance::<u16>::new(&crc::CRC_16_IBM_3740)
771 .checksum(&value)
772 .to_string(),
773 "CRC_16_IBM_SDLC" => CrcInstance::<u16>::new(&crc::CRC_16_IBM_SDLC)
774 .checksum(&value)
775 .to_string(),
776 "CRC_16_ISO_IEC_14443_3_A" => CrcInstance::<u16>::new(&crc::CRC_16_ISO_IEC_14443_3_A)
777 .checksum(&value)
778 .to_string(),
779 "CRC_16_KERMIT" => CrcInstance::<u16>::new(&crc::CRC_16_KERMIT)
780 .checksum(&value)
781 .to_string(),
782 "CRC_16_LJ1200" => CrcInstance::<u16>::new(&crc::CRC_16_LJ1200)
783 .checksum(&value)
784 .to_string(),
785 "CRC_16_M17" => CrcInstance::<u16>::new(&crc::CRC_16_M17)
786 .checksum(&value)
787 .to_string(),
788 "CRC_16_MAXIM_DOW" => CrcInstance::<u16>::new(&crc::CRC_16_MAXIM_DOW)
789 .checksum(&value)
790 .to_string(),
791 "CRC_16_MCRF4XX" => CrcInstance::<u16>::new(&crc::CRC_16_MCRF4XX)
792 .checksum(&value)
793 .to_string(),
794 "CRC_16_MODBUS" => CrcInstance::<u16>::new(&crc::CRC_16_MODBUS)
795 .checksum(&value)
796 .to_string(),
797 "CRC_16_NRSC_5" => CrcInstance::<u16>::new(&crc::CRC_16_NRSC_5)
798 .checksum(&value)
799 .to_string(),
800 "CRC_16_OPENSAFETY_A" => CrcInstance::<u16>::new(&crc::CRC_16_OPENSAFETY_A)
801 .checksum(&value)
802 .to_string(),
803 "CRC_16_OPENSAFETY_B" => CrcInstance::<u16>::new(&crc::CRC_16_OPENSAFETY_B)
804 .checksum(&value)
805 .to_string(),
806 "CRC_16_PROFIBUS" => CrcInstance::<u16>::new(&crc::CRC_16_PROFIBUS)
807 .checksum(&value)
808 .to_string(),
809 "CRC_16_RIELLO" => CrcInstance::<u16>::new(&crc::CRC_16_RIELLO)
810 .checksum(&value)
811 .to_string(),
812 "CRC_16_SPI_FUJITSU" => CrcInstance::<u16>::new(&crc::CRC_16_SPI_FUJITSU)
813 .checksum(&value)
814 .to_string(),
815 "CRC_16_T10_DIF" => CrcInstance::<u16>::new(&crc::CRC_16_T10_DIF)
816 .checksum(&value)
817 .to_string(),
818 "CRC_16_TELEDISK" => CrcInstance::<u16>::new(&crc::CRC_16_TELEDISK)
819 .checksum(&value)
820 .to_string(),
821 "CRC_16_TMS37157" => CrcInstance::<u16>::new(&crc::CRC_16_TMS37157)
822 .checksum(&value)
823 .to_string(),
824 "CRC_16_UMTS" => CrcInstance::<u16>::new(&crc::CRC_16_UMTS)
825 .checksum(&value)
826 .to_string(),
827 "CRC_16_USB" => CrcInstance::<u16>::new(&crc::CRC_16_USB)
828 .checksum(&value)
829 .to_string(),
830 "CRC_16_XMODEM" => CrcInstance::<u16>::new(&crc::CRC_16_XMODEM)
831 .checksum(&value)
832 .to_string(),
833 "CRC_17_CAN_FD" => CrcInstance::<u32>::new(&crc::CRC_17_CAN_FD)
834 .checksum(&value)
835 .to_string(),
836 "CRC_21_CAN_FD" => CrcInstance::<u32>::new(&crc::CRC_21_CAN_FD)
837 .checksum(&value)
838 .to_string(),
839 "CRC_24_BLE" => CrcInstance::<u32>::new(&crc::CRC_24_BLE)
840 .checksum(&value)
841 .to_string(),
842 "CRC_24_FLEXRAY_A" => CrcInstance::<u32>::new(&crc::CRC_24_FLEXRAY_A)
843 .checksum(&value)
844 .to_string(),
845 "CRC_24_FLEXRAY_B" => CrcInstance::<u32>::new(&crc::CRC_24_FLEXRAY_B)
846 .checksum(&value)
847 .to_string(),
848 "CRC_24_INTERLAKEN" => CrcInstance::<u32>::new(&crc::CRC_24_INTERLAKEN)
849 .checksum(&value)
850 .to_string(),
851 "CRC_24_LTE_A" => CrcInstance::<u32>::new(&crc::CRC_24_LTE_A)
852 .checksum(&value)
853 .to_string(),
854 "CRC_24_LTE_B" => CrcInstance::<u32>::new(&crc::CRC_24_LTE_B)
855 .checksum(&value)
856 .to_string(),
857 "CRC_24_OPENPGP" => CrcInstance::<u32>::new(&crc::CRC_24_OPENPGP)
858 .checksum(&value)
859 .to_string(),
860 "CRC_24_OS_9" => CrcInstance::<u32>::new(&crc::CRC_24_OS_9)
861 .checksum(&value)
862 .to_string(),
863 "CRC_30_CDMA" => CrcInstance::<u32>::new(&crc::CRC_30_CDMA)
864 .checksum(&value)
865 .to_string(),
866 "CRC_31_PHILIPS" => CrcInstance::<u32>::new(&crc::CRC_31_PHILIPS)
867 .checksum(&value)
868 .to_string(),
869 "CRC_32_AIXM" => CrcInstance::<u32>::new(&crc::CRC_32_AIXM)
870 .checksum(&value)
871 .to_string(),
872 "CRC_32_AUTOSAR" => CrcInstance::<u32>::new(&crc::CRC_32_AUTOSAR)
873 .checksum(&value)
874 .to_string(),
875 "CRC_32_BASE91_D" => CrcInstance::<u32>::new(&crc::CRC_32_BASE91_D)
876 .checksum(&value)
877 .to_string(),
878 "CRC_32_BZIP2" => CrcInstance::<u32>::new(&crc::CRC_32_BZIP2)
879 .checksum(&value)
880 .to_string(),
881 "CRC_32_CD_ROM_EDC" => CrcInstance::<u32>::new(&crc::CRC_32_CD_ROM_EDC)
882 .checksum(&value)
883 .to_string(),
884 "CRC_32_CKSUM" => CrcInstance::<u32>::new(&crc::CRC_32_CKSUM)
885 .checksum(&value)
886 .to_string(),
887 "CRC_32_ISCSI" => CrcInstance::<u32>::new(&crc::CRC_32_ISCSI)
888 .checksum(&value)
889 .to_string(),
890 "CRC_32_ISO_HDLC" => CrcInstance::<u32>::new(&crc::CRC_32_ISO_HDLC)
891 .checksum(&value)
892 .to_string(),
893 "CRC_32_JAMCRC" => CrcInstance::<u32>::new(&crc::CRC_32_JAMCRC)
894 .checksum(&value)
895 .to_string(),
896 "CRC_32_MEF" => CrcInstance::<u32>::new(&crc::CRC_32_MEF)
897 .checksum(&value)
898 .to_string(),
899 "CRC_32_MPEG_2" => CrcInstance::<u32>::new(&crc::CRC_32_MPEG_2)
900 .checksum(&value)
901 .to_string(),
902 "CRC_32_XFER" => CrcInstance::<u32>::new(&crc::CRC_32_XFER)
903 .checksum(&value)
904 .to_string(),
905 "CRC_40_GSM" => CrcInstance::<u64>::new(&crc::CRC_40_GSM)
906 .checksum(&value)
907 .to_string(),
908 "CRC_64_ECMA_182" => CrcInstance::<u64>::new(&crc::CRC_64_ECMA_182)
909 .checksum(&value)
910 .to_string(),
911 "CRC_64_GO_ISO" => CrcInstance::<u64>::new(&crc::CRC_64_GO_ISO)
912 .checksum(&value)
913 .to_string(),
914 "CRC_64_MS" => CrcInstance::<u64>::new(&crc::CRC_64_MS)
915 .checksum(&value)
916 .to_string(),
917 "CRC_64_REDIS" => CrcInstance::<u64>::new(&crc::CRC_64_REDIS)
918 .checksum(&value)
919 .to_string(),
920 "CRC_64_WE" => CrcInstance::<u64>::new(&crc::CRC_64_WE)
921 .checksum(&value)
922 .to_string(),
923 "CRC_64_XZ" => CrcInstance::<u64>::new(&crc::CRC_64_XZ)
924 .checksum(&value)
925 .to_string(),
926 "CRC_82_DARC" => CrcInstance::<u128>::new(&crc::CRC_82_DARC)
927 .checksum(&value)
928 .to_string(),
929 _ => return Err(format!("Invalid CRC algorithm: {algorithm}").into()),
930 };
931
932 Ok(checksum.into())
933}
934
935#[derive(Clone, Copy, Debug)]
936pub struct Crc;
937
938impl Function for Crc {
939 fn identifier(&self) -> &'static str {
940 "crc"
941 }
942
943 fn usage(&self) -> &'static str {
944 indoc! {
945 "Calculates a CRC of the `value`.The CRC `algorithm` used can be optionally specified.
946
947 This function is infallible if either the default `algorithm` value or a recognized-valid compile-time `algorithm` string literal is used. Otherwise, it is fallible."
948 }
949 }
950
951 fn category(&self) -> &'static str {
952 Category::Checksum.as_ref()
953 }
954
955 fn internal_failure_reasons(&self) -> &'static [&'static str] {
956 &[
957 "`value` is not a string.",
958 "`algorithm` is not a supported algorithm.",
959 ]
960 }
961
962 fn return_kind(&self) -> u16 {
963 kind::BYTES
964 }
965
966 fn parameters(&self) -> &'static [Parameter] {
967 PARAMETERS.as_slice()
968 }
969
970 fn examples(&self) -> &'static [Example] {
971 &[
972 example! {
973 title: "Create CRC checksum using the default algorithm",
974 source: r#"crc("foo")"#,
975 result: Ok(r#""2356372769""#),
976 },
977 example! {
978 title: "Create CRC checksum using the CRC_32_CKSUM algorithm",
979 source: r#"crc("foo", algorithm: "CRC_32_CKSUM")"#,
980 result: Ok(r#""4271552933""#),
981 },
982 ]
983 }
984
985 fn compile(
986 &self,
987 _state: &state::TypeState,
988 _ctx: &mut FunctionCompileContext,
989 arguments: ArgumentList,
990 ) -> Compiled {
991 let value = arguments.required("value");
992 let algorithm = arguments.optional("algorithm");
993
994 Ok(CrcFn { value, algorithm }.as_expr())
995 }
996}
997
998#[derive(Debug, Clone)]
999struct CrcFn {
1000 value: Box<dyn Expression>,
1001 algorithm: Option<Box<dyn Expression>>,
1002}
1003
1004impl FunctionExpression for CrcFn {
1005 fn resolve(&self, ctx: &mut Context) -> Resolved {
1006 let value = self.value.resolve(ctx)?;
1007 let algorithm = self
1008 .algorithm
1009 .map_resolve_with_default(ctx, || DEFAULT_ALGORITHM.clone())?;
1010
1011 let algorithm = algorithm.try_bytes_utf8_lossy()?.as_ref().to_uppercase();
1012 crc(value, &algorithm)
1013 }
1014
1015 fn type_def(&self, state: &state::TypeState) -> TypeDef {
1016 let algorithm = self.algorithm.as_ref();
1017 let valid_static_algo = algorithm.is_none()
1018 || algorithm
1019 .and_then(|algorithm| algorithm.resolve_constant(state))
1020 .and_then(|algorithm| algorithm.try_bytes_utf8_lossy().map(|s| s.to_string()).ok())
1021 .is_some_and(|algorithm| {
1022 VALID_ALGORITHMS.contains(&algorithm.to_uppercase().as_str())
1023 });
1024
1025 if valid_static_algo {
1026 TypeDef::bytes().infallible()
1027 } else {
1028 TypeDef::bytes().fallible()
1029 }
1030 }
1031}
1032
1033#[cfg(test)]
1034mod tests {
1035 use super::*;
1036 use crate::value;
1037
1038 test_function![
1039 crc => Crc;
1040
1041 crc_default {
1042 args: func_args![value: "foo"],
1043 want: Ok(value!(b"2356372769")),
1044 tdef: TypeDef::bytes().infallible(),
1045 }
1046
1047 crc_crc8 {
1048 args: func_args![value: "foo", algorithm: "CRC_8_MAXIM_DOW"],
1049 want: Ok(value!(b"18")),
1050 tdef: TypeDef::bytes().infallible(),
1051 }
1052
1053 crc_crc32 {
1054 args: func_args![value: "foo", algorithm: "CRC_32_CKSUM"],
1055 want: Ok(value!(b"4271552933")),
1056 tdef: TypeDef::bytes().infallible(),
1057 }
1058
1059 crc_crc64 {
1060 args: func_args![value: "foo", algorithm: "CRC_64_REDIS"],
1061 want: Ok(value!(b"12626267673720558670")),
1062 tdef: TypeDef::bytes().infallible(),
1063 }
1064
1065 crc_unknown {
1066 args: func_args![value: "foo", algorithm: "CRC_UNKNOWN"],
1067 want: Err("Invalid CRC algorithm: CRC_UNKNOWN"),
1068 tdef: TypeDef::bytes().fallible(),
1069 }
1070 ];
1071}