better collapse implementations

master
Avril 4 years ago
parent 8b37c3de40
commit 007136df26
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -4,7 +4,7 @@ description = "Small byte-sized generic key-value map type"
keywords = ["map", "table", "small", "key", "value"] keywords = ["map", "table", "small", "key", "value"]
repository = "https://github.com/notflan/smallmap" repository = "https://github.com/notflan/smallmap"
homepage= "https://git.flanchan.moe/flanchan/smallmap" homepage= "https://git.flanchan.moe/flanchan/smallmap"
version = "1.0.2" version = "1.1.2"
authors = ["Avril <flanchan@cumallover.me>"] authors = ["Avril <flanchan@cumallover.me>"]
edition = "2018" edition = "2018"
license = "MIT" license = "MIT"

@ -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]);

@ -48,10 +48,10 @@ mod init;
/// ///
/// Implementors should try to minimise collisions by making `collapse` return a relatively unique value if possible. /// Implementors should try to minimise collisions by making `collapse` return a relatively unique value if possible.
/// But it is not required. /// 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). /// 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 pub trait Collapse: Eq
{ {
/// Create the index key for this instance. This is similar in use to `Hash::hash()`. /// Create the index key for this instance. This is similar in use to `Hash::hash()`.
@ -353,30 +353,63 @@ impl<K: Collapse, V> IntoIterator for Map<K,V>
} }
} }
use std::hash::{Hash, Hasher,};
/// Helper trait implementing `Collapse` for types that can be represents as a slice of bytes. impl<T: Hash+ Eq> Collapse for T
///
/// 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<T> Collapse for T
where T: CollapseMemory
{ {
fn collapse(&self) -> u8 { 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;
}
};
mod primitives; ($nm:ident, i8) => {
pub use primitives::*; #[inline(always)] fn $nm(&mut self, i: i8)
{
self.0 ^= i as u8;
}
};
mod defaults; ($nm:ident, $ty:tt) => {
pub use defaults::*; #[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
}
}
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;

@ -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);
Loading…
Cancel
Save