1#![cfg_attr(not(feature = "std"), no_std)]
22#![cfg_attr(
23 all(feature = "nightly", target_arch = "aarch64"),
24 feature(stdsimd, aarch64_target_feature)
25)]
26
27#[deny(missing_docs)]
28#[cfg(test)]
29#[macro_use]
30extern crate quickcheck;
31
32#[macro_use]
33extern crate cfg_if;
34
35#[cfg(feature = "std")]
36use std as core;
37
38use core::fmt;
39use core::hash;
40
41mod baseline;
42mod combine;
43mod specialized;
44mod table;
45
46#[derive(Clone)]
47enum State {
48 Baseline(baseline::State),
49 Specialized(specialized::State),
50}
51
52#[derive(Clone)]
53pub struct Hasher {
55 amount: u64,
56 state: State,
57}
58
59const DEFAULT_INIT_STATE: u32 = 0;
60
61impl Hasher {
62 pub fn new() -> Self {
67 Self::new_with_initial(DEFAULT_INIT_STATE)
68 }
69
70 pub fn new_with_initial(init: u32) -> Self {
75 Self::internal_new_specialized(init).unwrap_or_else(|| Self::internal_new_baseline(init))
76 }
77
78 #[doc(hidden)]
79 pub fn internal_new_baseline(init: u32) -> Self {
81 Hasher {
82 amount: 0,
83 state: State::Baseline(baseline::State::new(init)),
84 }
85 }
86
87 #[doc(hidden)]
88 pub fn internal_new_specialized(init: u32) -> Option<Self> {
90 {
91 if let Some(state) = specialized::State::new(init) {
92 return Some(Hasher {
93 amount: 0,
94 state: State::Specialized(state),
95 });
96 }
97 }
98 None
99 }
100
101 pub fn update(&mut self, buf: &[u8]) {
103 self.amount += buf.len() as u64;
104 match self.state {
105 State::Baseline(ref mut state) => state.update(buf),
106 State::Specialized(ref mut state) => state.update(buf),
107 }
108 }
109
110 pub fn finalize(self) -> u32 {
112 match self.state {
113 State::Baseline(state) => state.finalize(),
114 State::Specialized(state) => state.finalize(),
115 }
116 }
117
118 pub fn reset(&mut self) {
120 self.amount = 0;
121 match self.state {
122 State::Baseline(ref mut state) => state.reset(),
123 State::Specialized(ref mut state) => state.reset(),
124 }
125 }
126
127 pub fn combine(&mut self, other: &Self) {
129 self.amount += other.amount;
130 let other_crc = other.clone().finalize();
131 match self.state {
132 State::Baseline(ref mut state) => state.combine(other_crc, other.amount),
133 State::Specialized(ref mut state) => state.combine(other_crc, other.amount),
134 }
135 }
136}
137
138impl fmt::Debug for Hasher {
139 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
140 f.debug_struct("crc32fast::Hasher").finish()
141 }
142}
143
144impl Default for Hasher {
145 fn default() -> Self {
146 Self::new()
147 }
148}
149
150impl hash::Hasher for Hasher {
151 fn write(&mut self, bytes: &[u8]) {
152 self.update(bytes)
153 }
154
155 fn finish(&self) -> u64 {
156 u64::from(self.clone().finalize())
157 }
158}
159
160#[cfg(test)]
161mod test {
162 use super::Hasher;
163
164 quickcheck! {
165 fn combine(bytes_1: Vec<u8>, bytes_2: Vec<u8>) -> bool {
166 let mut hash_a = Hasher::new();
167 hash_a.update(&bytes_1);
168 hash_a.update(&bytes_2);
169 let mut hash_b = Hasher::new();
170 hash_b.update(&bytes_2);
171 let mut hash_c = Hasher::new();
172 hash_c.update(&bytes_1);
173 hash_c.combine(&hash_b);
174
175 hash_a.finalize() == hash_c.finalize()
176 }
177 }
178}