Skip to main content

farmhash_ffi/
lib.rs

1use std::hash::Hasher;
2use std::iter::Extend;
3
4use libc::size_t;
5
6extern "C" {
7    fn Hash64(s: *const u8, len: size_t) -> u64;
8    fn Hash64WithSeed(s: *const u8, len: size_t, seed: u64) -> u64;
9}
10
11// Given a slice of bytes, return its 64-bit hash.
12fn hash_64(input: &[u8]) -> u64 {
13    unsafe { Hash64(input.as_ptr(), input.len() as size_t) }
14}
15
16// Given a slice of bytes and a seed, return its 64-bit hash.
17fn hash_64_with_seed(input: &[u8], seed: u64) -> u64 {
18    unsafe { Hash64WithSeed(input.as_ptr(), input.len() as size_t, seed) }
19}
20
21/// `Hash64` implements the 64-bit version of FarmHash.
22#[derive(Debug, Default)]
23pub struct Hash64 {
24    buf: Vec<u8>,
25    seed: Option<u64>,
26}
27
28impl Hash64 {
29    /// Use a `Hash64` with a pre-defined seed.
30    pub fn with_seed(seed: u64) -> Hash64 {
31        Hash64 {
32            buf: Default::default(),
33            seed: Some(seed),
34        }
35    }
36}
37
38impl Hasher for Hash64 {
39    fn write(&mut self, bytes: &[u8]) {
40        self.buf.extend(bytes);
41    }
42
43    fn finish(&self) -> u64 {
44        if let Some(s) = self.seed {
45            hash_64_with_seed(&self.buf, s)
46        } else {
47            hash_64(&self.buf)
48        }
49    }
50}
51
52#[cfg(test)]
53mod tests {
54    use std::hash::Hasher;
55
56    use super::Hash64;
57
58    #[test]
59    fn no_seed_64() {
60        const EXPECTED: u64 = 18084869015357591102;
61
62        let mut h = Hash64::default();
63        h.write(b"farmhash");
64
65        assert_eq!(EXPECTED, h.finish());
66    }
67
68    #[test]
69    fn seed_64() {
70        const EXPECTED: u64 = 15795874029479571151;
71
72        let mut h = Hash64::with_seed(7);
73        h.write(b"farmhash");
74
75        assert_eq!(EXPECTED, h.finish());
76    }
77}