1#![deprecated(note = "use the `crc32fast` crate instead")]
7
8#[macro_use]
9extern crate cfg_if;
10
11#[cfg(test)]
12#[macro_use]
13extern crate quickcheck;
14
15cfg_if! {
16 if #[cfg(not(simd))] {
17 mod other;
18 use self::other as imp;
19 } else if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
20 mod x86;
21 use self::x86 as imp;
22 } else {
23 mod other;
24 use self::other as imp;
25 }
26}
27
28#[derive(Debug)]
29pub struct Hardware(bool);
30
31impl Hardware {
32 #[inline]
33 pub fn detect() -> Hardware {
34 Hardware(imp::detect())
35 }
36
37 #[inline]
38 pub fn calculate(
39 &self,
40 crc: u32,
41 data: &[u8],
42 fallback: fn(u32, &[u8]) -> u32,
43 ) -> u32 {
44 if self.0 {
45 unsafe { imp::calculate(crc, data, fallback) }
46 } else {
47 fallback(crc, data)
48 }
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 extern crate miniz_sys;
55 extern crate rand;
56 extern crate rayon;
57
58 use self::rand::Rng;
59 use self::rayon::prelude::*;
60 use super::Hardware;
61
62 fn fallback(a: u32, b: &[u8]) -> u32 {
63 unsafe {
64 miniz_sys::mz_crc32(a as _, b.as_ptr(), b.len()) as u32
65 }
66 }
67
68 fn random_chunks(iters: usize, lo: usize, hi: usize) {
69 let hardware = Hardware::detect();
70
71 (0..iters)
72 .into_par_iter()
73 .for_each_with(Vec::new(), |data, _| {
74 let mut rng = rand::thread_rng();
75 let init = rng.gen::<u32>();
76 let len = rng.gen_range(lo, hi);
77 data.resize(len, 0u8);
78 rng.fill(&mut data[..]);
79
80 assert_eq!(
81 fallback(init, &data),
82 hardware.calculate(init, &data, fallback),
83 );
84 });
85 }
86
87 #[test]
88 fn random_small() {
89 random_chunks(1000, 0, 256);
90 }
91
92 #[test]
93 fn random_med() {
94 random_chunks(1000, 256, 16 * 1024);
95 }
96
97 #[test]
98 fn random_large() {
99 random_chunks(1000, 0, 1024 * 1024);
100 }
101
102 quickcheck! {
103 fn prop(crc: u32, xs: Vec<u8>) -> bool {
104 fallback(crc, &xs) == Hardware::detect().calculate(crc, &xs, fallback)
105 }
106 }
107}