1use siphasher::sip::SipHasher;
5use std::hash::Hasher;
6
7fn tea(input: &[u32; 4], buf: &mut [u32; 2]) {
12 const DELTA: u32 = 0x9e3779b9;
13 let mut sum = 0u32;
14 let mut v = buf.clone();
15 for _ in 0..16 {
16 sum = sum.wrapping_add(DELTA);
17 v[0] = v[0].wrapping_add(
18 (v[1] << 4).wrapping_add(input[0])
19 ^ v[1].wrapping_add(sum)
20 ^ (v[1] >> 5).wrapping_add(input[1]),
21 );
22 v[1] = v[1].wrapping_add(
23 (v[0] << 4).wrapping_add(input[2])
24 ^ v[0].wrapping_add(sum)
25 ^ (v[0] >> 5).wrapping_add(input[3]),
26 );
27 }
28 buf[0] = buf[0].wrapping_add(v[0]);
29 buf[1] = buf[1].wrapping_add(v[1]);
30}
31
32fn str_hash(input: &[u8], padding: u32, out: &mut [u32; 4]) {
33 debug_assert!(input.len() <= out.len() * 4);
34 *out = [padding; 4];
35 let mut out_ix = 0;
36 let mut v = padding;
37 for i in 0..input.len() {
38 v = (input[i] as u32).wrapping_add(v << 8);
39 if i % 4 == 3 {
40 out[out_ix] = v;
41 out_ix += 1;
42 v = padding;
43 }
44 }
45 if out_ix < 4 {
46 out[out_ix] = v;
47 }
48}
49
50pub fn tea_hash_filename(name: &[u8]) -> u32 {
52 let mut buf = [0x67452301, 0xefcdab89];
53 let mut len = name.len() as u32;
54 name.chunks(16).for_each(|chunk| {
55 let mut k = [0; 4];
56 let padding = len | (len << 8) | (len << 16) | (len << 24);
57 len -= 16;
58 str_hash(chunk, padding, &mut k);
59 tea(&k, &mut buf);
60 });
61 buf[0]
62}
63
64pub fn casefold_encrypt_hash_filename(name: &[u8], dirhash_key: &[u8; 16]) -> u32 {
67 let mut hasher = SipHasher::new_with_key(dirhash_key);
68 hasher.write(name);
69 hasher.finish() as u32
70}