git_zero_core/pack/
crc.rs1pub fn crc32(bytes: &[u8]) -> u32 {
3 let mut crc = Crc32::new();
4 crc.update(bytes);
5 crc.value()
6}
7
8pub(super) struct Crc32(u32);
10
11impl Crc32 {
12 pub(super) const fn new() -> Self {
13 Self(u32::MAX)
14 }
15 pub(super) fn value(&self) -> u32 {
16 !self.0
17 }
18 pub(super) fn update(&mut self, bytes: &[u8]) {
19 const TABLE: [[u32; 256]; 8] = crc_tables();
20 let mut crc = self.0;
21 let mut chunks = bytes.chunks_exact(8);
22 for chunk in &mut chunks {
23 let low = u32::from_le_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]) ^ crc;
24 crc = TABLE[7][usize::from(low as u8)]
25 ^ TABLE[6][usize::from((low >> 8) as u8)]
26 ^ TABLE[5][usize::from((low >> 16) as u8)]
27 ^ TABLE[4][(low >> 24) as usize]
28 ^ TABLE[3][usize::from(chunk[4])]
29 ^ TABLE[2][usize::from(chunk[5])]
30 ^ TABLE[1][usize::from(chunk[6])]
31 ^ TABLE[0][usize::from(chunk[7])];
32 }
33 for &byte in chunks.remainder() {
34 crc = (crc >> 8) ^ TABLE[0][usize::from(crc as u8 ^ byte)];
35 }
36 self.0 = crc;
37 }
38}
39
40const fn crc_tables() -> [[u32; 256]; 8] {
41 let mut table = [[0; 256]; 8];
42 let mut index = 0;
43 while index < 256 {
44 let mut value = index as u32;
45 let mut bit = 0;
46 while bit < 8 {
47 value = (value >> 1) ^ if value & 1 != 0 { 0xedb8_8320 } else { 0 };
48 bit += 1;
49 }
50 table[0][index] = value;
51 index += 1;
52 }
53 let mut slice = 1;
54 while slice < 8 {
55 index = 0;
56 while index < 256 {
57 let previous = table[slice - 1][index];
58 table[slice][index] = (previous >> 8) ^ table[0][(previous & 255) as usize];
59 index += 1;
60 }
61 slice += 1;
62 }
63 table
64}