From 007136df26f89209555059e0f80f6e9e43dc9ca0 Mon Sep 17 00:00:00 2001 From: Avril Date: Sun, 20 Sep 2020 17:39:06 +0100 Subject: [PATCH] better collapse implementations --- Cargo.toml | 2 +- src/defaults.rs | 17 ----------- src/lib.rs | 77 +++++++++++++++++++++++++++++++++-------------- src/primitives.rs | 56 ---------------------------------- 4 files changed, 56 insertions(+), 96 deletions(-) delete mode 100644 src/defaults.rs delete mode 100644 src/primitives.rs diff --git a/Cargo.toml b/Cargo.toml index 04dc72a..90d796e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ description = "Small byte-sized generic key-value map type" keywords = ["map", "table", "small", "key", "value"] repository = "https://github.com/notflan/smallmap" homepage= "https://git.flanchan.moe/flanchan/smallmap" -version = "1.0.2" +version = "1.1.2" authors = ["Avril "] edition = "2018" license = "MIT" diff --git a/src/defaults.rs b/src/defaults.rs deleted file mode 100644 index d15c4cf..0000000 --- a/src/defaults.rs +++ /dev/null @@ -1,17 +0,0 @@ -//! Default implementors -use super::*; - -macro_rules! collapse { - ($ty:ty) => { - impl CollapseMemory for $ty - { - fn as_memory(&self) -> &[u8] - { - self.as_ref() - } - } - }; -} - -collapse!(str); -collapse!([u8]); diff --git a/src/lib.rs b/src/lib.rs index 5624298..24ea784 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -48,10 +48,10 @@ mod init; /// /// Implementors should try to minimise collisions by making `collapse` return a relatively unique value if possible. /// But it is not required. -/// Primitive `Eq` types already implement this, as well as `str` and `[u8]`. +/// It is automatically implemented for types implementing the `Hash` trait. /// A simple folding implementation is provided for byte slices here [`collapse_iter()`](collapse_iter). /// -/// Integer types implement this through the modulo of itself over 256, whereas byte slice types implement it through an XOR fold over itself. It doesn't matter though, the programmer is free to implement it how she chooses. +/// The default implementation has integer types implement this through the modulo of itself over 256, whereas byte slice types implement it through an XOR fold over itself. It doesn't matter though, the programmer is free to implement it how she chooses. pub trait Collapse: Eq { /// Create the index key for this instance. This is similar in use to `Hash::hash()`. @@ -353,30 +353,63 @@ impl IntoIterator for Map } } - -/// Helper trait implementing `Collapse` for types that can be represents as a slice of bytes. -/// -/// The `collapse` implementation used is a XOR fold over all bytes. -pub trait CollapseMemory: Eq -{ - /// Get the memory representation of this instance to be used to key calculations in `Map`. - fn as_memory(&self) -> &[u8]; -} -impl Collapse for T -where T: CollapseMemory +use std::hash::{Hash, Hasher,}; +impl Collapse for T { fn collapse(&self) -> u8 { - collapse(self.as_memory()) + struct CollapseHasher(u8); + macro_rules! hash_type { + + ($nm:ident, u8) => { + #[inline(always)] fn $nm(&mut self, i: u8) + { + self.0 ^= i; + } + }; + + ($nm:ident, i8) => { + #[inline(always)] fn $nm(&mut self, i: i8) + { + self.0 ^= i as u8; + } + }; + + ($nm:ident, $ty:tt) => { + #[inline] fn $nm(&mut self, i: $ty) + { + self.0 ^= (i % MAX as $ty) as u8; + } + }; + } + impl Hasher for CollapseHasher + { + #[inline] fn finish(&self) -> u64 + { + self.0 as u64 + } + #[inline] fn write(&mut self, buffer: &[u8]) + { + self.0 ^= collapse(buffer); + } + hash_type!(write_u8, u8); + hash_type!(write_i8, i8); + hash_type!(write_i16, i16); + hash_type!(write_u16, u16); + hash_type!(write_i32, i32); + hash_type!(write_u32, u32); + hash_type!(write_i64, i64); + hash_type!(write_u64, u64); + hash_type!(write_u128, u128); + + hash_type!(write_isize, isize); + hash_type!(write_usize, usize); + } + + let mut h = CollapseHasher(0); + self.hash(&mut h); + h.0 } } - - -mod primitives; -pub use primitives::*; - -mod defaults; -pub use defaults::*; - #[cfg(test)] mod tests; diff --git a/src/primitives.rs b/src/primitives.rs deleted file mode 100644 index 53cdcbe..0000000 --- a/src/primitives.rs +++ /dev/null @@ -1,56 +0,0 @@ -//! Implementing `Collapse` for primitive types -use super::*; - -macro_rules! collapse { - (char) => { - impl Collapse for char - { - #[inline] fn collapse(&self) -> u8 - { - (u32::from(*self) % (MAX as u32)) as u8 - } - } - }; - ($type:ty) => { - impl Collapse for $type - { - #[inline] fn collapse(&self) -> u8 - { - const _: &[(); 1] = &[(); (((MAX as $type) as usize) == MAX) as usize]; - (*self % MAX as Self) as u8 - } - } - }; -} - -impl Collapse for bool -{ - #[inline] fn collapse(&self) -> u8 - { - *self as u8 - } -} -impl Collapse for u8 -{ - #[inline] fn collapse(&self) -> u8 - { - *self - } -} - -impl Collapse for i8 -{ - #[inline] fn collapse(&self) -> u8 - { - *self as u8 - } -} -collapse!(char); -collapse!(u16); -collapse!(i16); -collapse!(i32); -collapse!(u32); -collapse!(u64); -collapse!(i64); -collapse!(i128); -collapse!(u128);