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
const HASH_SIZE: usize = 243;
const STATE_SIZE: usize = HASH_SIZE * 3;
const T: [i8; 11] = [1, 0, -1, 0, 1, -1, 0, 0, -1, 1, 0];
pub type State = [i8; STATE_SIZE];
pub type Hash = [i8; HASH_SIZE];
pub struct Curl {
idx: [i16; STATE_SIZE + 1],
state: State,
}
impl Curl {
pub fn new() -> Self {
let mut idx = [0 as i16; STATE_SIZE + 1];
for i in 0..idx.len() {
idx[i] = ((i * 364) % 729) as i16;
}
Curl {
idx: idx,
state: [0; STATE_SIZE],
}
}
pub fn absorb(&mut self, input: &[i8], offset: usize, size: usize) {
assert!(offset+size <= input.len());
for c in input[offset..offset+size].chunks(HASH_SIZE) {
self.fill_state_array_with_slice(c);
self.transform();
}
}
pub fn transform(&mut self) {
let mut state_copy = &mut [0; STATE_SIZE + 1];
self.fill_state_copy_array(&mut state_copy);
for _ in 0..27 {
for i in 0..STATE_SIZE {
let i = i as usize;
self.state[i] = T[(state_copy[self.idx[i] as usize] + (state_copy[self.idx[i + 1] as usize] << 2) + 5) as usize];
}
self.fill_state_copy_array(&mut state_copy);
}
}
pub fn squeeze_into(&mut self, out: &mut [i8], offset: usize) {
assert!(offset+HASH_SIZE <= out.len());
&mut out[offset..offset+HASH_SIZE].copy_from_slice(&self.state[0..HASH_SIZE]);
self.transform();
}
pub fn state(&self) -> State {
self.state
}
pub fn indices(&self) -> [i16; STATE_SIZE + 1] {
self.idx
}
fn fill_state_array_with_slice(&mut self, input: &[i8]) {
assert!(input.len() <= STATE_SIZE);
&mut self.state[..input.len()].copy_from_slice(input);
}
fn fill_state_copy_array(&mut self, dst: &mut [i8; STATE_SIZE + 1]) {
&mut dst[..STATE_SIZE].copy_from_slice(&self.state);
}
}