#![deny(missing_docs)]
#![cfg_attr(test, feature(test))]
#[cfg(test)]
extern crate test;
use std::ops;
pub mod raw;
#[cfg(test)]
mod tests;
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct Hash {
hash: u64,
}
impl Hash {
#[inline]
pub fn new(string: &str) -> Hash {
let string = string.as_bytes();
let mut b = 0;
let first_byte = raw::map_first(*string.get(0).unwrap_or(&0)) as u64;
let mut res = 0;
let mut n = 1u8;
loop {
b += 1;
if n == 0 || b >= string.len() {
break;
}
if let Some(x) = raw::filter(res as u8, string[b]) {
res <<= 8;
res |= x as u64;
n <<= 1;
}
}
Hash {
hash: res | (first_byte << 56),
}
}
}
impl Into<u64> for Hash {
#[inline]
fn into(self) -> u64 {
self.hash
}
}
impl ops::Sub for Hash {
type Output = Difference;
#[inline]
fn sub(self, rhs: Hash) -> Difference {
Difference {
xor: self.hash ^ rhs.hash,
}
}
}
#[derive(Copy, Clone)]
pub struct Difference {
xor: u64,
}
impl Difference {
#[inline]
pub fn dist(self) -> u32 {
(self.xor as u8).count_ones() as u32
+ ((self.xor >> 8 ) as u8).count_ones() as u32 * 2
+ ((self.xor >> 16) as u8).count_ones() as u32 * 3
+ ((self.xor >> 24) as u8).count_ones() as u32 * 5
+ ((self.xor >> 32) as u8).count_ones() as u32 * 8
+ ((self.xor >> 40) as u8).count_ones() as u32 * 13
+ ((self.xor >> 48) as u8).count_ones() as u32 * 21
+ ((self.xor >> 56) as u8).count_ones() as u32 * 34
}
#[inline]
pub fn xor(self) -> u64 {
self.xor
}
#[inline]
pub fn hamming(self) -> u32 {
self.xor.count_ones()
}
#[inline]
pub fn similar(self) -> bool {
self.dist() < 15
}
}
#[deprecated]
pub fn similar(a: &str, b: &str) -> bool {
(Hash::new(a) - Hash::new(b)).similar()
}