use std::hash::Hasher;
#[derive(Default)]
pub(super) struct IntHasher([u8; 8], #[cfg(debug_assertions)] bool);
impl Hasher for IntHasher {
fn write(&mut self, bytes: &[u8]) {
#[cfg(debug_assertions)]
{
if self.1 {
panic!("socket hash function can only be written to once");
} else {
self.1 = true;
}
if bytes.len() > 8 {
panic!("only a maximum of 8 bytes can be hashed");
}
}
(&mut self.0[..bytes.len()]).copy_from_slice(bytes);
}
#[inline]
fn finish(&self) -> u64 {
u64::from_ne_bytes(self.0)
}
}
#[cfg(test)]
mod tests {
use super::IntHasher;
use curl::multi::Socket;
use quickcheck_macros::quickcheck;
use std::hash::{Hash, Hasher};
#[test]
#[should_panic]
fn hash_of_more_than_8_bytes_panics() {
"hello".hash(&mut IntHasher::default());
}
#[quickcheck]
fn hash_socket_is_deterministic(socket: Socket) {
let mut hasher_a = IntHasher::default();
socket.hash(&mut hasher_a);
let mut hasher_b = IntHasher::default();
socket.hash(&mut hasher_b);
assert_eq!(hasher_a.finish(), hasher_b.finish());
}
#[quickcheck]
fn hash_of_two_sockets_are_equal_iff_sockets_are_equal(a: Socket, b: Socket) {
let mut hasher_a = IntHasher::default();
a.hash(&mut hasher_a);
let mut hasher_b = IntHasher::default();
b.hash(&mut hasher_b);
if a == b {
assert_eq!(hasher_a.finish(), hasher_b.finish());
} else {
assert_ne!(hasher_a.finish(), hasher_b.finish());
}
}
}