fasthash_fork/
meow.rs

1//! `Meow` - A Fast Non-cryptographic Hash
2//!
3//! (C) Copyright 2018-2019 by Molly Rocket, Inc. (https://mollyrocket.com)
4//!
5//! See https://mollyrocket.com/meowhash for details.
6//!
7//! # Example
8//!
9//! ```
10//! use std::hash::Hash;
11//!
12//! use fasthash::{meow, HasherExt};
13//!
14//! fn hash<T: Hash>(t: &T) -> u128 {
15//!     let mut s: meow::Hasher = Default::default();
16//!     t.hash(&mut s);
17//!     s.finish_ext()
18//! }
19//!
20//! let h = meow::hash128(b"hello world\xff");
21//!
22//! assert_eq!(h, hash(&"hello world"));
23//! ```
24//!
25use std::mem;
26use std::os::raw::c_void;
27
28use derive_more::{Deref, From, Into};
29use rand::Rng;
30
31use crate::ffi;
32use crate::hasher::{self, FastHash};
33
34/// Generate hash seeds for `meow`
35#[repr(transparent)]
36#[derive(Clone, Copy, Debug, PartialEq, Eq, Deref, From, Into)]
37pub struct Seed(pub [u8; 128]);
38
39impl Default for Seed {
40    fn default() -> Self {
41        Seed([
42            0x32, 0x43, 0xF6, 0xA8, 0x88, 0x5A, 0x30, 0x8D, 0x31, 0x31, 0x98, 0xA2, 0xE0, 0x37,
43            0x07, 0x34, 0x4A, 0x40, 0x93, 0x82, 0x22, 0x99, 0xF3, 0x1D, 0x00, 0x82, 0xEF, 0xA9,
44            0x8E, 0xC4, 0xE6, 0xC8, 0x94, 0x52, 0x82, 0x1E, 0x63, 0x8D, 0x01, 0x37, 0x7B, 0xE5,
45            0x46, 0x6C, 0xF3, 0x4E, 0x90, 0xC6, 0xCC, 0x0A, 0xC2, 0x9B, 0x7C, 0x97, 0xC5, 0x0D,
46            0xD3, 0xF8, 0x4D, 0x5B, 0x5B, 0x54, 0x70, 0x91, 0x79, 0x21, 0x6D, 0x5D, 0x98, 0x97,
47            0x9F, 0xB1, 0xBD, 0x13, 0x10, 0xBA, 0x69, 0x8D, 0xFB, 0x5A, 0xC2, 0xFF, 0xD7, 0x2D,
48            0xBD, 0x01, 0xAD, 0xFB, 0x7B, 0x8E, 0x1A, 0xFE, 0xD6, 0xA2, 0x67, 0xE9, 0x6B, 0xA7,
49            0xC9, 0x04, 0x5F, 0x12, 0xC7, 0xF9, 0x92, 0x4A, 0x19, 0x94, 0x7B, 0x39, 0x16, 0xCF,
50            0x70, 0x80, 0x1F, 0x2E, 0x28, 0x58, 0xEF, 0xC1, 0x66, 0x36, 0x92, 0x0D, 0x87, 0x15,
51            0x74, 0xE6,
52        ])
53    }
54}
55
56impl From<u64> for Seed {
57    fn from(seed: u64) -> Self {
58        let mut b = [0; 128];
59        unsafe {
60            ffi::MeowHashExpandSeed(
61                mem::size_of::<u64>() as u64,
62                &seed as *const _ as *mut _,
63                b.as_mut_ptr(),
64            );
65        }
66        Seed(b)
67    }
68}
69
70impl From<u128> for Seed {
71    fn from(seed: u128) -> Self {
72        let mut b = [0; 128];
73        unsafe {
74            ffi::MeowHashExpandSeed(
75                mem::size_of::<u128>() as u64,
76                &seed as *const _ as *mut _,
77                b.as_mut_ptr(),
78            );
79        }
80        Seed(b)
81    }
82}
83
84impl From<hasher::Seed> for Seed {
85    #[inline(always)]
86    fn from(mut seed: hasher::Seed) -> Seed {
87        let mut b = [0; 128];
88        seed.fill(&mut b);
89        Seed(b)
90    }
91}
92
93/// `Meow` 128-bit hash functions
94///
95/// # Example
96///
97/// ```
98/// use fasthash::{meow::Hash128, FastHash};
99///
100/// assert_eq!(Hash128::hash(b"hello"), 287823689163471951033538203431451692478);
101/// assert_eq!(Hash128::hash_with_seed(b"hello", 123u64.into()), 60552855887416612272420513695414607282);
102/// assert_eq!(Hash128::hash(b"helloworld"), 149236362065540004012572291671223589700);
103/// ```
104#[derive(Clone, Default)]
105pub struct Hash128;
106
107impl FastHash for Hash128 {
108    type Hash = u128;
109    type Seed = Seed;
110
111    #[inline(always)]
112    fn hash_with_seed<T: AsRef<[u8]>>(bytes: T, seed: Seed) -> u128 {
113        let mut hash = 0u128;
114        unsafe {
115            ffi::MeowHash128(
116                bytes.as_ref().as_ptr() as *const _,
117                bytes.as_ref().len() as i32,
118                seed.as_ptr() as *mut c_void,
119                (&mut hash) as *mut _ as *mut _,
120            )
121        }
122        hash
123    }
124}
125
126trivial_hasher! {
127    /// # Example
128    ///
129    /// ```
130    /// use std::hash::Hasher as _;
131    ///
132    /// use fasthash::{meow::Hasher, FastHasher, HasherExt};
133    ///
134    /// let mut h = Hasher::new();
135    ///
136    /// h.write(b"hello");
137    /// assert_eq!(h.finish_ext(), 287823689163471951033538203431451692478);
138    ///
139    /// h.write(b"world");
140    /// assert_eq!(h.finish_ext(), 149236362065540004012572291671223589700);
141    /// ```
142    Hasher(Hash128) -> u128
143}
144
145/// `Meow` 128-bit hash functions for a byte array.
146///
147/// # Example
148///
149/// ```
150/// use fasthash::meow::hash128;
151///
152/// assert_eq!(hash128("helloworld"), 149236362065540004012572291671223589700);
153/// ```
154#[inline(always)]
155pub fn hash128<T: AsRef<[u8]>>(v: T) -> u128 {
156    Hash128::hash(v)
157}
158
159/// `Meow` 128-bit hash function for a byte array.
160/// For convenience, a 1024-bit seed is also hashed into the result.
161///
162/// # Example
163///
164/// ```
165/// use fasthash::meow::hash128_with_seed;
166///
167/// assert_eq!(hash128_with_seed("helloworld", 123u64), 170522160844008905659318271476576158043);
168/// ```
169#[inline(always)]
170pub fn hash128_with_seed<T: AsRef<[u8]>, S: Into<Seed>>(v: T, seed: S) -> u128 {
171    Hash128::hash_with_seed(v, seed.into())
172}