OXYGENHUB
◆ agents-in-readme oxygen / vendor / crc-fast / src / crc32 / algorithm.rs
4.2 KiB · Rust · last changed Strata: the cloud stores send through ureq, so every release target links 1 month ago source blame history raw
1
// Copyright 2025 Don MacAskill. Licensed under MIT or Apache-2.0.
2
3
//! This module provides the CRC-32 algorithm implementations for areas where it differs from
4
//! CRC-64.
5
6
#![cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64"))]
7
8
use crate::enums::Reflector;
9
use crate::structs::CrcState;
10
use crate::traits::{ArchOps, EnhancedCrcWidth};
11
12
impl EnhancedCrcWidth for crate::structs::Width32 {
13
    #[inline(always)]
14
    fn load_constants(reflected: bool) -> [[u64; 2]; 4] {
15
        crate::crc32::width32_ops::load_constants(reflected)
16
    }
17
18
    #[inline(always)]
19
    unsafe fn create_state<T: ArchOps>(
20
        value: Self::Value,
21
        reflected: bool,
22
        ops: &T,
23
    ) -> CrcState<T::Vector>
24
    where
25
        T::Vector: Copy,
26
    {
27
        let vector = if reflected {
28
            // For reflected mode, state goes in the low 32 bits
29
            ops.create_vector_from_u32(value, false)
30
        } else {
31
            // For non-reflected mode, state goes in high 32 bits of the
32
            // high 64-bit part of the 128-bit register (need to shift 12 bytes)
33
            ops.create_vector_from_u32(value, true)
34
        };
35
36
        CrcState {
37
            value: vector,
38
            reflected,
39
        }
40
    }
41
42
    #[inline(always)]
43
    unsafe fn extract_result<T: ArchOps>(vector: T::Vector, reflected: bool, ops: &T) -> Self::Value
44
    where
45
        T::Vector: Copy,
46
    {
47
        // Extract u64s from the vector
48
        let u64s = ops.extract_u64s(vector);
49
50
        if reflected {
51
            // In reflected mode, the result is in the low 32 bits of the low 64 bits
52
            u64s[0] as u32
53
        } else {
54
            // In non-reflected mode, the result is in the high 32 bits of the low 64 bits
55
            (u64s[1] >> 32) as u32
56
        }
57
    }
58
59
    #[inline(always)]
60
    unsafe fn fold_16<T: ArchOps>(
61
        state: &mut CrcState<T::Vector>,
62
        coeff: T::Vector,
63
        data_to_xor: T::Vector,
64
        ops: &T,
65
    ) where
66
        T::Vector: Copy,
67
    {
68
        crate::crc32::width32_ops::fold_16(state, coeff, data_to_xor, ops)
69
    }
70
71
    /// CRC-32 specific implementation for folding 8 bytes to 4 bytes
72
    #[inline(always)]
73
    unsafe fn fold_width<T: ArchOps>(state: &mut CrcState<T::Vector>, high: u64, low: u64, ops: &T)
74
    where
75
        T::Vector: Copy,
76
    {
77
        crate::crc32::width32_ops::fold_width(state, high, low, ops)
78
    }
79
80
    #[inline(always)]
81
    unsafe fn barrett_reduction<T: ArchOps>(
82
        state: &CrcState<T::Vector>,
83
        poly: u64,
84
        mu: u64,
85
        ops: &T,
86
    ) -> Self::Value
87
    where
88
        T::Vector: Copy,
89
    {
90
        let u64s = crate::crc32::width32_ops::barrett_reduction(state, poly, mu, ops);
91
        if state.reflected {
92
            u64s[1] as u32
93
        } else {
94
            (u64s[0] >> 32) as u32
95
        }
96
    }
97
98
    #[inline(always)]
99
    unsafe fn create_coefficient<T: ArchOps>(
100
        high: u64,
101
        low: u64,
102
        _reflected: bool,
103
        ops: &T,
104
    ) -> T::Vector
105
    where
106
        T::Vector: Copy,
107
    {
108
        crate::crc32::width32_ops::create_coefficient(high, low, ops)
109
    }
110
111
    #[inline(always)]
112
    unsafe fn perform_final_reduction<T: ArchOps>(
113
        state: T::Vector,
114
        reflected: bool,
115
        keys: &[u64; 23],
116
        ops: &T,
117
    ) -> Self::Value
118
    where
119
        T::Vector: Copy,
120
    {
121
        let u64s = crate::crc32::width32_ops::perform_final_reduction(state, reflected, keys, ops);
122
        if reflected {
123
            u64s[1] as u32
124
        } else {
125
            (u64s[0] >> 32) as u32
126
        }
127
    }
128
129
    #[inline(always)]
130
    fn get_last_bytes_table_ptr(reflected: bool, remaining_len: usize) -> (*const u8, usize) {
131
        crate::crc32::width32_ops::get_last_bytes_table_ptr(reflected, remaining_len)
132
    }
133
}
134
135
/// Process inputs smaller than 16 bytes
136
#[inline]
137
#[cfg_attr(
138
    any(target_arch = "x86", target_arch = "x86_64"),
139
    target_feature(enable = "ssse3,sse4.1,pclmulqdq")
140
)]
141
#[cfg_attr(target_arch = "aarch64", target_feature(enable = "aes"))]
142
pub(crate) unsafe fn process_0_to_15<T: ArchOps, W: EnhancedCrcWidth>(
143
    data: &[u8],
144
    state: &mut CrcState<T::Vector>,
145
    reflector: &Reflector<T::Vector>,
146
    keys: &[u64; 23],
147
    ops: &T,
148
) -> W::Value
149
where
150
    T::Vector: Copy,
151
{
152
    crate::crc32::width32_ops::process_0_to_15::<T, W>(data, state, reflector, keys, ops)
153
}