1#![cfg_attr(not(feature = "std"), no_std)]
12
13use core::{fmt, hash::{BuildHasherDefault, Hasher}, marker::PhantomData};
14
15#[cfg(feature = "std")]
33pub type IntMap<K, V> = std::collections::HashMap<K, V, BuildNoHashHasher<K>>;
34
35#[cfg(feature = "std")]
53pub type IntSet<T> = std::collections::HashSet<T, BuildNoHashHasher<T>>;
54
55pub type BuildNoHashHasher<T> = BuildHasherDefault<NoHashHasher<T>>;
75
76#[cfg(debug_assertions)]
107pub struct NoHashHasher<T>(u64, bool, PhantomData<T>);
108
109#[cfg(not(debug_assertions))]
110pub struct NoHashHasher<T>(u64, PhantomData<T>);
111
112impl<T> fmt::Debug for NoHashHasher<T> {
113 #[cfg(debug_assertions)]
114 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
115 f.debug_tuple("NoHashHasher").field(&self.0).field(&self.1).finish()
116 }
117
118 #[cfg(not(debug_assertions))]
119 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
120 f.debug_tuple("NoHashHasher").field(&self.0).finish()
121 }
122}
123
124impl<T> Default for NoHashHasher<T> {
125 #[cfg(debug_assertions)]
126 fn default() -> Self {
127 NoHashHasher(0, false, PhantomData)
128 }
129
130 #[cfg(not(debug_assertions))]
131 fn default() -> Self {
132 NoHashHasher(0, PhantomData)
133 }
134}
135
136impl<T> Clone for NoHashHasher<T> {
137 #[cfg(debug_assertions)]
138 fn clone(&self) -> Self {
139 NoHashHasher(self.0, self.1, self.2)
140 }
141
142 #[cfg(not(debug_assertions))]
143 fn clone(&self) -> Self {
144 NoHashHasher(self.0, self.1)
145 }
146}
147
148impl<T> Copy for NoHashHasher<T> {}
149
150pub trait IsEnabled {}
186
187impl IsEnabled for u8 {}
188impl IsEnabled for u16 {}
189impl IsEnabled for u32 {}
190impl IsEnabled for u64 {}
191impl IsEnabled for usize {}
192impl IsEnabled for i8 {}
193impl IsEnabled for i16 {}
194impl IsEnabled for i32 {}
195impl IsEnabled for i64 {}
196impl IsEnabled for isize {}
197
198#[cfg(not(debug_assertions))]
199impl<T: IsEnabled> Hasher for NoHashHasher<T> {
200 fn write(&mut self, _: &[u8]) {
201 panic!("Invalid use of NoHashHasher")
202 }
203
204 fn write_u8(&mut self, n: u8) { self.0 = u64::from(n) }
205 fn write_u16(&mut self, n: u16) { self.0 = u64::from(n) }
206 fn write_u32(&mut self, n: u32) { self.0 = u64::from(n) }
207 fn write_u64(&mut self, n: u64) { self.0 = n }
208 fn write_usize(&mut self, n: usize) { self.0 = n as u64 }
209
210 fn write_i8(&mut self, n: i8) { self.0 = n as u64 }
211 fn write_i16(&mut self, n: i16) { self.0 = n as u64 }
212 fn write_i32(&mut self, n: i32) { self.0 = n as u64 }
213 fn write_i64(&mut self, n: i64) { self.0 = n as u64 }
214 fn write_isize(&mut self, n: isize) { self.0 = n as u64 }
215
216 fn finish(&self) -> u64 { self.0 }
217}
218
219#[cfg(debug_assertions)]
220impl<T: IsEnabled> Hasher for NoHashHasher<T> {
221 fn write(&mut self, _: &[u8]) {
222 panic!("Invalid use of NoHashHasher")
223 }
224
225 fn write_u8(&mut self, n: u8) {
226 assert!(!self.1, "NoHashHasher: second write attempt detected.");
227 self.0 = u64::from(n);
228 self.1 = true
229 }
230
231 fn write_u16(&mut self, n: u16) {
232 assert!(!self.1, "NoHashHasher: second write attempt detected.");
233 self.0 = u64::from(n);
234 self.1 = true
235 }
236
237 fn write_u32(&mut self, n: u32) {
238 assert!(!self.1, "NoHashHasher: second write attempt detected.");
239 self.0 = u64::from(n);
240 self.1 = true
241 }
242
243 fn write_u64(&mut self, n: u64) {
244 assert!(!self.1, "NoHashHasher: second write attempt detected.");
245 self.0 = n;
246 self.1 = true
247 }
248
249 fn write_usize(&mut self, n: usize) {
250 assert!(!self.1, "NoHashHasher: second write attempt detected.");
251 self.0 = n as u64;
252 self.1 = true
253 }
254
255 fn write_i8(&mut self, n: i8) {
256 assert!(!self.1, "NoHashHasher: second write attempt detected.");
257 self.0 = n as u64;
258 self.1 = true
259 }
260
261 fn write_i16(&mut self, n: i16) {
262 assert!(!self.1, "NoHashHasher: second write attempt detected.");
263 self.0 = n as u64;
264 self.1 = true
265 }
266
267 fn write_i32(&mut self, n: i32) {
268 assert!(!self.1, "NoHashHasher: second write attempt detected.");
269 self.0 = n as u64;
270 self.1 = true
271 }
272
273 fn write_i64(&mut self, n: i64) {
274 assert!(!self.1, "NoHashHasher: second write attempt detected.");
275 self.0 = n as u64;
276 self.1 = true
277 }
278
279 fn write_isize(&mut self, n: isize) {
280 assert!(!self.1, "NoHashHasher: second write attempt detected.");
281 self.0 = n as u64;
282 self.1 = true
283 }
284
285 fn finish(&self) -> u64 {
286 self.0
287 }
288}
289
290#[cfg(test)]
291mod tests {
292 use super::*;
293
294 #[test]
295 fn ok() {
296 let mut h1 = NoHashHasher::<u8>::default();
297 h1.write_u8(42);
298 assert_eq!(42, h1.finish());
299
300 let mut h2 = NoHashHasher::<u16>::default();
301 h2.write_u16(42);
302 assert_eq!(42, h2.finish());
303
304 let mut h3 = NoHashHasher::<u32>::default();
305 h3.write_u32(42);
306 assert_eq!(42, h3.finish());
307
308 let mut h4 = NoHashHasher::<u64>::default();
309 h4.write_u64(42);
310 assert_eq!(42, h4.finish());
311
312 let mut h5 = NoHashHasher::<usize>::default();
313 h5.write_usize(42);
314 assert_eq!(42, h5.finish());
315
316 let mut h6 = NoHashHasher::<i8>::default();
317 h6.write_i8(42);
318 assert_eq!(42, h6.finish());
319
320 let mut h7 = NoHashHasher::<i16>::default();
321 h7.write_i16(42);
322 assert_eq!(42, h7.finish());
323
324 let mut h8 = NoHashHasher::<i32>::default();
325 h8.write_i32(42);
326 assert_eq!(42, h8.finish());
327
328 let mut h9 = NoHashHasher::<i64>::default();
329 h9.write_i64(42);
330 assert_eq!(42, h9.finish());
331
332 let mut h10 = NoHashHasher::<isize>::default();
333 h10.write_isize(42);
334 assert_eq!(42, h10.finish())
335 }
336
337 #[cfg(debug_assertions)]
338 #[test]
339 #[should_panic]
340 fn u8_double_usage() {
341 let mut h = NoHashHasher::<u8>::default();
342 h.write_u8(42);
343 h.write_u8(43);
344 }
345
346 #[cfg(debug_assertions)]
347 #[test]
348 #[should_panic]
349 fn u16_double_usage() {
350 let mut h = NoHashHasher::<u16>::default();
351 h.write_u16(42);
352 h.write_u16(43);
353 }
354
355 #[cfg(debug_assertions)]
356 #[test]
357 #[should_panic]
358 fn u32_double_usage() {
359 let mut h = NoHashHasher::<u32>::default();
360 h.write_u32(42);
361 h.write_u32(43);
362 }
363
364 #[cfg(debug_assertions)]
365 #[test]
366 #[should_panic]
367 fn u64_double_usage() {
368 let mut h = NoHashHasher::<u64>::default();
369 h.write_u64(42);
370 h.write_u64(43);
371 }
372
373 #[cfg(debug_assertions)]
374 #[test]
375 #[should_panic]
376 fn usize_double_usage() {
377 let mut h = NoHashHasher::<usize>::default();
378 h.write_usize(42);
379 h.write_usize(43);
380 }
381
382 #[cfg(debug_assertions)]
383 #[test]
384 #[should_panic]
385 fn i8_double_usage() {
386 let mut h = NoHashHasher::<i8>::default();
387 h.write_i8(42);
388 h.write_i8(43);
389 }
390
391 #[cfg(debug_assertions)]
392 #[test]
393 #[should_panic]
394 fn i16_double_usage() {
395 let mut h = NoHashHasher::<i16>::default();
396 h.write_i16(42);
397 h.write_i16(43);
398 }
399
400 #[cfg(debug_assertions)]
401 #[test]
402 #[should_panic]
403 fn i32_double_usage() {
404 let mut h = NoHashHasher::<i32>::default();
405 h.write_i32(42);
406 h.write_i32(43);
407 }
408
409 #[cfg(debug_assertions)]
410 #[test]
411 #[should_panic]
412 fn i64_double_usage() {
413 let mut h = NoHashHasher::<i64>::default();
414 h.write_i64(42);
415 h.write_i64(43);
416 }
417
418 #[cfg(debug_assertions)]
419 #[test]
420 #[should_panic]
421 fn isize_double_usage() {
422 let mut h = NoHashHasher::<isize>::default();
423 h.write_isize(42);
424 h.write_isize(43);
425 }
426}
427