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