1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
use std::{
    borrow::Borrow,
    collections::hash_map::DefaultHasher,
    hash::{Hash, Hasher},
};

use super::pearson_hashing::T;

pub fn hash16<T: Borrow<[u8]>>(x0: usize, x: T) -> u16 {
    let ret = T[x0] as u16;
    let v = x.borrow();
    let mut hasher = DefaultHasher::new();
    v.hash(&mut hasher);
    ret ^ Hasher::finish(&hasher) as u16
}

pub fn hash16_mod<T: Borrow<[u8]>, const MOD: u16>(x0: usize, x: T) -> u16 {
    let ret = T[x0] as u16;
    let v = x.borrow();
    let mut hasher = DefaultHasher::new();
    v.hash(&mut hasher);
    ret ^ (Hasher::finish(&hasher) % (MOD as u64)) as u16
}

#[derive(Clone)]
pub struct Pearson<const MOD: usize> {
    acc: u8,
}

pub trait VaryHasher<R>: Clone {
    const MOD: usize;
    fn new(init: usize) -> Self;
    fn finish(&self) -> R;
    fn write_u8(&mut self, i: u8);
    fn write_u16(&mut self, i: u16);
    fn write(&mut self, bytes: &[u8]);
}

impl<const MOD: usize> VaryHasher<u8> for Pearson<MOD> {
    const MOD: usize = MOD;
    fn new(init: usize) -> Self {
        Self { acc: T[init % 256] }
    }
    fn finish(&self) -> u8 {
        self.acc
    }
    fn write_u8(&mut self, i: u8) {
        if MOD as u8 == 0 {
            self.acc = T[(self.acc ^ i) as usize];
        } else {
            self.acc = T[(self.acc ^ i) as usize] % (MOD as u8);
        }
    }
    fn write_u16(&mut self, _: u16) {
        panic!()
    }
    fn write(&mut self, bytes: &[u8]) {
        for i in bytes {
            VaryHasher::<u8>::write_u8(self, *i);
        }
    }
}

#[derive(Clone)]
#[repr(transparent)]
pub struct MyDefaultHasher<const MOD: usize>(DefaultHasher);

impl<const MOD: usize> VaryHasher<u16> for MyDefaultHasher<MOD> {
    const MOD: usize = MOD;
    fn new(init: usize) -> Self {
        let mut r = MyDefaultHasher(DefaultHasher::new());
        r.0.write_usize(init);
        r
    }
    fn finish(&self) -> u16 {
        if MOD as u64 == 0 {
            self.0.finish() as u16
        } else {
            (self.0.finish() % (MOD as u64)) as u16
        }
    }
    fn write_u8(&mut self, i: u8) {
        self.0.write_u8(i)
    }
    fn write_u16(&mut self, i: u16) {
        self.0.write_u16(i)
    }
    fn write(&mut self, bytes: &[u8]) {
        self.0.write(bytes)
    }
}