crc_fast/
structs.rs

1// Copyright 2025 Don MacAskill. Licensed under MIT or Apache-2.0.
2
3#![allow(dead_code)]
4
5use crate::traits::{CrcCalculator, CrcWidth};
6use crate::{arch, cache, CrcAlgorithm, CrcParams};
7
8/// CRC-32 width implementation
9#[derive(Clone, Copy)]
10pub struct Width32;
11
12impl CrcWidth for Width32 {
13    const WIDTH: u32 = 32;
14    type Value = u32;
15}
16
17/// CRC-64 width implementation
18#[derive(Clone, Copy)]
19pub struct Width64;
20
21impl CrcWidth for Width64 {
22    const WIDTH: u32 = 64;
23    type Value = u64;
24}
25
26/// CRC State wrapper to manage the SIMD operations and reflection mode
27#[derive(Debug, Clone, Copy)]
28pub struct CrcState<T> {
29    pub value: T,
30    pub reflected: bool,
31}
32
33pub(crate) struct Calculator {}
34
35impl CrcCalculator for Calculator {
36    #[inline(always)]
37    fn calculate(state: u64, data: &[u8], params: CrcParams) -> u64 {
38        unsafe { arch::update(state, data, params) }
39    }
40}
41
42impl CrcParams {
43    /// Creates custom CRC parameters for a given set of Rocksoft CRC parameters.
44    ///
45    /// Uses an internal cache to avoid regenerating folding keys for identical parameter sets.
46    /// The first call with a given set of parameters will generate and cache the keys, while
47    /// subsequent calls with the same parameters will use the cached keys for optimal performance.
48    ///
49    /// Does not support mis-matched refin/refout parameters, so both must be true or both false.
50    ///
51    /// Rocksoft parameters for lots of variants: https://reveng.sourceforge.io/crc-catalogue/all.htm
52    pub fn new(
53        name: &'static str,
54        width: u8,
55        poly: u64,
56        init: u64,
57        reflected: bool,
58        xorout: u64,
59        check: u64,
60    ) -> Self {
61        let keys_array = cache::get_or_generate_keys(width, poly, reflected);
62        let keys = crate::CrcKeysStorage::from_keys_fold_256(keys_array);
63
64        let algorithm = match width {
65            32 => CrcAlgorithm::Crc32Custom,
66            64 => CrcAlgorithm::Crc64Custom,
67            _ => panic!("Unsupported width: {width}",),
68        };
69
70        Self {
71            algorithm,
72            name,
73            width,
74            poly,
75            init,
76            refin: reflected,
77            refout: reflected,
78            xorout,
79            check,
80            keys,
81        }
82    }
83
84    /// Gets a key at the specified index, returning 0 if out of bounds.
85    /// This provides safe access regardless of internal key storage format.
86    #[inline(always)]
87    pub fn get_key(self, index: usize) -> u64 {
88        self.keys.get_key(index)
89    }
90
91    /// Gets a key at the specified index, returning None if out of bounds.
92    /// This provides optional key access for cases where bounds checking is needed.
93    #[inline(always)]
94    pub fn get_key_checked(self, index: usize) -> Option<u64> {
95        if index < self.keys.key_count() {
96            Some(self.keys.get_key(index))
97        } else {
98            None
99        }
100    }
101
102    /// Returns the number of keys available in this CrcParams instance.
103    #[inline(always)]
104    pub fn key_count(self) -> usize {
105        self.keys.key_count()
106    }
107}