/rust/registry/src/index.crates.io-1949cf8c6b5b557f/zlib-rs-0.6.8/src/adler32/generic.rs
Line | Count | Source |
1 | | use super::{BASE, NMAX}; |
2 | | |
3 | | const UNROLL_MORE: bool = true; |
4 | | |
5 | | // macros for loop unrolling |
6 | | macro_rules! do1 { |
7 | | ($sum1:expr, $sum2:expr, $chunk:expr, $i:expr) => { |
8 | | // SAFETY: $i is bounded by either [0, 8] or [0, 16], and the caller ensures the chunk is |
9 | | // long enough, so we can omit bound checking. |
10 | | $sum1 += unsafe { *$chunk.get_unchecked($i) } as u32; |
11 | | $sum2 += $sum1; |
12 | | }; |
13 | | } |
14 | | |
15 | | macro_rules! do2 { |
16 | | ($sum1:expr, $sum2:expr, $chunk:expr, $i:expr) => { |
17 | | do1!($sum1, $sum2, $chunk, $i); |
18 | | do1!($sum1, $sum2, $chunk, $i + 1); |
19 | | }; |
20 | | } |
21 | | |
22 | | macro_rules! do4 { |
23 | | ($sum1:expr, $sum2:expr, $chunk:expr, $i:expr) => { |
24 | | do2!($sum1, $sum2, $chunk, $i); |
25 | | do2!($sum1, $sum2, $chunk, $i + 2); |
26 | | }; |
27 | | } |
28 | | |
29 | | macro_rules! do8 { |
30 | | ($sum1:expr, $sum2:expr, $chunk:expr, $i:expr) => { |
31 | | do4!($sum1, $sum2, $chunk, $i); |
32 | | do4!($sum1, $sum2, $chunk, $i + 4); |
33 | | }; |
34 | | } |
35 | | |
36 | | macro_rules! do16 { |
37 | | ($sum1:expr, $sum2:expr, $chunk:expr) => { |
38 | | do8!($sum1, $sum2, $chunk, 0); |
39 | | do8!($sum1, $sum2, $chunk, 8); |
40 | | }; |
41 | | } |
42 | | |
43 | 0 | pub fn adler32_rust(mut adler: u32, buf: &[u8]) -> u32 { |
44 | | /* split Adler-32 into component sums */ |
45 | 0 | let mut sum2 = (adler >> 16) & 0xffff; |
46 | 0 | adler &= 0xffff; |
47 | | |
48 | | /* in case user likes doing a byte at a time, keep it fast */ |
49 | 0 | if buf.len() == 1 { |
50 | 0 | return adler32_len_1(adler, buf, sum2); |
51 | 0 | } |
52 | | |
53 | | /* initial Adler-32 value (deferred check for len == 1 speed) */ |
54 | 0 | if buf.is_empty() { |
55 | 0 | return adler | (sum2 << 16); |
56 | 0 | } |
57 | | |
58 | | /* in case short lengths are provided, keep it somewhat fast */ |
59 | 0 | if buf.len() < 16 { |
60 | 0 | return adler32_len_16(adler, buf, sum2); |
61 | 0 | } |
62 | | |
63 | 0 | let mut it = buf.chunks_exact(NMAX as usize); |
64 | 0 | for big_chunk in it.by_ref() { |
65 | | const N: usize = if UNROLL_MORE { 16 } else { 8 } as usize; |
66 | 0 | let it = big_chunk.chunks_exact(N); |
67 | 0 | for chunk in it { |
68 | 0 | if N == 16 { |
69 | 0 | do16!(adler, sum2, chunk); |
70 | 0 | } else { |
71 | 0 | do8!(adler, sum2, chunk, 0); |
72 | 0 | } |
73 | | } |
74 | | |
75 | 0 | adler %= BASE; |
76 | 0 | sum2 %= BASE; |
77 | | } |
78 | | |
79 | | /* do remaining bytes (less than NMAX, still just one modulo) */ |
80 | 0 | adler32_len_64(adler, it.remainder(), sum2) |
81 | 0 | } |
82 | | |
83 | 0 | pub(crate) fn adler32_len_1(mut adler: u32, buf: &[u8], mut sum2: u32) -> u32 { |
84 | 0 | adler += buf[0] as u32; |
85 | 0 | adler %= BASE; |
86 | 0 | sum2 += adler; |
87 | 0 | sum2 %= BASE; |
88 | 0 | adler | (sum2 << 16) |
89 | 0 | } |
90 | | |
91 | 0 | pub(crate) fn adler32_len_16(mut adler: u32, buf: &[u8], mut sum2: u32) -> u32 { |
92 | 0 | for b in buf { |
93 | 0 | adler += (*b) as u32; |
94 | 0 | sum2 += adler; |
95 | 0 | } |
96 | | |
97 | 0 | adler %= BASE; |
98 | 0 | sum2 %= BASE; /* only added so many BASE's */ |
99 | | /* return recombined sums */ |
100 | 0 | adler | (sum2 << 16) |
101 | 0 | } |
102 | | |
103 | 0 | pub(crate) fn adler32_len_64(mut adler: u32, buf: &[u8], mut sum2: u32) -> u32 { |
104 | | const N: usize = if UNROLL_MORE { 16 } else { 8 }; |
105 | 0 | let mut it = buf.chunks_exact(N); |
106 | 0 | for chunk in it.by_ref() { |
107 | 0 | if N == 16 { |
108 | 0 | do16!(adler, sum2, chunk); |
109 | 0 | } else { |
110 | 0 | do8!(adler, sum2, chunk, 0); |
111 | 0 | } |
112 | | } |
113 | | |
114 | | /* Process tail (len < 16). */ |
115 | 0 | adler32_len_16(adler, it.remainder(), sum2) |
116 | 0 | } |