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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#![cfg_attr(not(test), no_std)]
use core::{mem, slice};
#[allow(non_snake_case)]
fn lua_bind_hash_bytes(data_bytes: &[u8]) -> u64 {
let mut len = data_bytes.len() as u64;
let mut hash_vals: [u64; 4] = [
0x60ea27eeadc0b5d5,
0xc2b2ae3d27d4eb4e,
0xffffffffffffffff,
0x61c8864e7a143578,
];
let mut hash_vals_mid = [0u64; 4];
let hash_vals_end: [u64; 4] = [
0x3c6ef3630bd7950e,
0x1bbcd8c2f5e54380,
0x779b185ebca87000,
0xe6c617af2a1c0000
];
let hash_vals_end_shift: [u64; 4] = [
0x3f,
0x39,
0x34,
0x2e
];
const MULT1: u64 = 0x87bcb65480000000;
const MULT2: u64 = 0xdef35b010f796ca9;
const MULT3: u64 = 0x9e3779b185ebca87;
const MULT4: u64 = 0xc2b2ae3d27d4eb4f;
const MULT5: u64 = 0x93ea75a780000000;
const MULT6: u64 = 0x27d4eb2f165667c5;
const ADD1: u64 = 0x85ebca77c2b2ae63;
const ADD2: u64 = 0x165667b19e3779f9;
let mut lVar5 = 0x27d4eb2f165667c4;
let chunks_32 = data_bytes.chunks_exact(32);
let chunks_8 = chunks_32.remainder().chunks_exact(8);
let chunks_4 = chunks_8.remainder().chunks_exact(4);
let data_1 = chunks_4.remainder().iter();
let data_32 = chunks_32.map(|chunk| unsafe {
slice::from_raw_parts(
chunk.as_ptr() as *const u64,
32usize / mem::size_of::<u64>()
)
});
let data_8 = chunks_8.map(|chunk| unsafe { *(chunk.as_ptr() as *const u64) });
let mut data_4 = chunks_4.map(|chunk| unsafe { *(chunk.as_ptr() as *const u32) });
if len >= 0x20 {
for chunk in data_32 {
for i in 0..4 {
hash_vals[i] += chunk[i] * MULT4;
hash_vals_mid[i] = hash_vals[i] >> 0x21 | hash_vals[i] * 0x80000000;
hash_vals[i] = hash_vals_mid[i] * MULT3;
}
}
let mut val: u64 = 0;
for i in 0..4 {
val += hash_vals_mid[i] * hash_vals_end[i] | hash_vals[i] >> hash_vals_end_shift[i];
}
val = (val ^ (hash_vals_mid[0] * MULT1 | hash_vals_mid[0] * MULT2 >> 0x21) * MULT3) * MULT3;
for i in 1..4 {
val = (val + ADD1 ^ (hash_vals_mid[i] * MULT1 | hash_vals_mid[i] * MULT2 >> 0x21) * MULT3) * MULT3;
}
val += ADD1;
lVar5 = val;
}
len += lVar5;
for n in data_8 {
len = (n * MULT5 | (n * MULT4) >> 0x21) *
MULT3 ^ len;
len = (len >> 0x25 | len << 0x1b) * MULT3 + ADD1;
}
if let Some(n) = data_4.nth(0) {
len = n as u64 * MULT3 ^ len;
len = (len >> 0x29 | len << 0x17) * MULT4 + ADD2;
}
for n in data_1 {
len = *n as u64 * MULT6 ^ len;
len = (len >> 0x35 | len << 0xb) * MULT3;
}
let uVar3 = (len ^ len >> 0x21) * MULT4;
let uVar3 = (uVar3 ^ uVar3 >> 0x1d) * ADD2;
uVar3 ^ uVar3 >> 0x20
}
pub fn lua_bind_hash<S: AsRef<[u8]>>(string: S) -> u64 {
lua_bind_hash_bytes(string.as_ref())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_all_test_strings() {
let tests = vec![
("password", 0xe58325ff3537c13a),
("password1234", 0xa26a67b576fe1e83),
("FIGHTER_STATUS_DAMAGE_WORK_FLOAT_VECOR_CORRECT_STICK_X", 0xa4d50a730e36970e),
];
for test in tests {
assert_eq!(lua_bind_hash(test.0), test.1);
}
}
}