vrl/stdlib/
crc.rs

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}