1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use std::default::Default;
use std::hash::Hasher;
const INIT: u32 = 0xB7_04_CE;
include! { concat!(env!("OUT_DIR"), "/table.inc") }
#[derive(Copy,Clone,PartialEq,Eq)]
pub struct Crc24Hasher {
state: u32
}
impl Crc24Hasher {
pub fn init(v: u32) -> Crc24Hasher {
Crc24Hasher { state: v & 0xFF_FF_FF }
}
pub fn new() -> Crc24Hasher {
Crc24Hasher { state: INIT }
}
}
impl Default for Crc24Hasher {
fn default() -> Crc24Hasher {
Crc24Hasher::new()
}
}
impl Hasher for Crc24Hasher {
fn finish(&self) -> u64 { self.state as u64 }
fn write(&mut self, msg: &[u8]) {
let mut s = self.state;
for &octet in msg.iter() {
let index = ((octet as u32) ^ (s >> 16)) & 0xFF;
s = (s << 8) ^ CRC24_TABLE[index as usize];
}
self.state = s & 0xFF_FF_FF;
}
}
pub fn hash_raw(octets: &[u8]) -> u32 {
let mut h: Crc24Hasher = Default::default();
h.write(octets);
h.finish() as u32
}
#[cfg(test)]
mod test {
const CRC24_INIT: u32 = 0x__b7_04_ce;
const CRC24_POLY: u32 = 0x1_86_4c_fb;
fn crc_octets(octets: &[u8]) -> u32 {
let mut crc = CRC24_INIT;
for &octet in octets.iter() {
crc ^= (octet as u32) << 16;
for _ in 0..8 {
crc <<= 1;
if (crc & 0x1_00_00_00) != 0 {
crc ^= CRC24_POLY;
}
}
}
crc & 0xFF_FF_FF
}
fn test_compare_impls(octets: &[u8]) -> bool {
let h1 = crc_octets(octets);
let h2 = super::hash_raw(octets);
h1 == h2
}
#[test]
fn test() {
assert!(test_compare_impls(b""));
assert!(test_compare_impls(b"x"));
assert!(test_compare_impls(b"sg"));
assert!(test_compare_impls(b"crc"));
assert!(test_compare_impls(b"test"));
}
}