Skip to content

Commit a961930

Browse files
committed
Start moving core::hash to support a Hash trait. Add to_bytes::IterBytes trait.
1 parent ab53819 commit a961930

File tree

3 files changed

+408
-34
lines changed

3 files changed

+408
-34
lines changed

src/libcore/hash.rs

Lines changed: 102 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import io::Writer;
1717
import io::WriterUtil;
18+
import to_bytes::IterBytes;
1819

1920
export Streaming, State;
2021
export default_state;
@@ -33,6 +34,21 @@ export hash_u16;
3334
export hash_u8;
3435
export hash_uint;
3536

37+
/// Types that can meaningfully be hashed should implement this.
38+
trait Hash {
39+
pure fn hash_keyed(k0: u64, k1: u64) -> u64;
40+
}
41+
42+
// When we have default methods, won't need this.
43+
trait HashUtil {
44+
pure fn hash() -> u64;
45+
}
46+
47+
impl <A: Hash> A: HashUtil {
48+
#[inline(always)]
49+
pure fn hash() -> u64 { self.hash_keyed(0,0) }
50+
}
51+
3652
/// Streaming hash-functions should implement this.
3753
trait Streaming {
3854
fn input((&[const u8]));
@@ -43,38 +59,97 @@ trait Streaming {
4359
fn reset();
4460
}
4561

46-
fn keyed(k0: u64, k1: u64, f: fn(s: &State)) -> u64 {
47-
let s = &State(k0, k1);
48-
f(s);
49-
s.result_u64()
62+
impl <A: IterBytes> A: Hash {
63+
#[inline(always)]
64+
pure fn hash_keyed(k0: u64, k1: u64) -> u64 {
65+
unchecked {
66+
let s = &State(k0, k1);
67+
for self.iter_le_bytes |bytes| {
68+
s.input(bytes);
69+
}
70+
s.result_u64()
71+
}
72+
}
5073
}
5174

52-
pure fn hash_bytes_keyed(buf: &[const u8], k0: u64, k1: u64) -> u64 {
53-
unchecked { keyed(k0, k1, |s| s.input(buf)) }
75+
// implementations
76+
77+
pure fn hash_keyed_2<A: IterBytes,
78+
B: IterBytes>(a: &A, b: &B,
79+
k0: u64, k1: u64) -> u64 {
80+
unchecked {
81+
let s = &State(k0, k1);
82+
for a.iter_le_bytes |bytes| { s.input(bytes); }
83+
for b.iter_le_bytes |bytes| { s.input(bytes); }
84+
s.result_u64()
85+
}
5486
}
55-
pure fn hash_str_keyed(s: &str, k0: u64, k1: u64) -> u64 {
56-
unsafe {
57-
do str::as_buf(s) |buf, len| {
58-
do vec::unsafe::form_slice(buf, len) |slice| {
59-
hash_bytes_keyed(slice, k0, k1)
60-
}
61-
}
87+
88+
pure fn hash_keyed_3<A: IterBytes,
89+
B: IterBytes,
90+
C: IterBytes>(a: &A, b: &B, c: &C,
91+
k0: u64, k1: u64) -> u64 {
92+
unchecked {
93+
let s = &State(k0, k1);
94+
for a.iter_le_bytes |bytes| { s.input(bytes); }
95+
for b.iter_le_bytes |bytes| { s.input(bytes); }
96+
for c.iter_le_bytes |bytes| { s.input(bytes); }
97+
s.result_u64()
98+
}
99+
}
100+
101+
pure fn hash_keyed_4<A: IterBytes,
102+
B: IterBytes,
103+
C: IterBytes,
104+
D: IterBytes>(a: &A, b: &B, c: &C, d: &D,
105+
k0: u64, k1: u64) -> u64 {
106+
unchecked {
107+
let s = &State(k0, k1);
108+
for a.iter_le_bytes |bytes| { s.input(bytes); }
109+
for b.iter_le_bytes |bytes| { s.input(bytes); }
110+
for c.iter_le_bytes |bytes| { s.input(bytes); }
111+
for d.iter_le_bytes |bytes| { s.input(bytes); }
112+
s.result_u64()
113+
}
114+
}
115+
116+
pure fn hash_keyed_5<A: IterBytes,
117+
B: IterBytes,
118+
C: IterBytes,
119+
D: IterBytes,
120+
E: IterBytes>(a: &A, b: &B, c: &C, d: &D, e: &E,
121+
k0: u64, k1: u64) -> u64 {
122+
unchecked {
123+
let s = &State(k0, k1);
124+
for a.iter_le_bytes |bytes| { s.input(bytes); }
125+
for b.iter_le_bytes |bytes| { s.input(bytes); }
126+
for c.iter_le_bytes |bytes| { s.input(bytes); }
127+
for d.iter_le_bytes |bytes| { s.input(bytes); }
128+
for e.iter_le_bytes |bytes| { s.input(bytes); }
129+
s.result_u64()
62130
}
63131
}
132+
133+
pure fn hash_bytes_keyed(val: &[const u8], k0: u64, k1: u64) -> u64 {
134+
val.hash_keyed(k0, k1)
135+
}
136+
pure fn hash_str_keyed(val: &str, k0: u64, k1: u64) -> u64 {
137+
val.hash_keyed(k0, k1)
138+
}
64139
pure fn hash_u64_keyed(val: u64, k0: u64, k1: u64) -> u64 {
65-
unchecked { keyed(k0, k1, |s| s.write_le_u64(val)) }
140+
val.hash_keyed(k0, k1)
66141
}
67142
pure fn hash_u32_keyed(val: u32, k0: u64, k1: u64) -> u64 {
68-
unchecked { keyed(k0, k1, |s| s.write_le_u32(val)) }
143+
val.hash_keyed(k0, k1)
69144
}
70145
pure fn hash_u16_keyed(val: u16, k0: u64, k1: u64) -> u64 {
71-
unchecked { keyed(k0, k1, |s| s.write_le_u16(val)) }
146+
val.hash_keyed(k0, k1)
72147
}
73148
pure fn hash_u8_keyed(val: u8, k0: u64, k1: u64) -> u64 {
74-
unchecked { keyed(k0, k1, |s| s.write_u8(val)) }
149+
val.hash_keyed(k0, k1)
75150
}
76151
pure fn hash_uint_keyed(val: uint, k0: u64, k1: u64) -> u64 {
77-
unchecked { keyed(k0, k1, |s| s.write_le_uint(val)) }
152+
val.hash_keyed(k0, k1)
78153
}
79154

80155
pure fn hash_bytes(val: &[const u8]) -> u64 { hash_bytes_keyed(val, 0, 0) }
@@ -89,10 +164,13 @@ pure fn hash_uint(val: uint) -> u64 { hash_uint_keyed(val, 0, 0) }
89164
// Implement State as SipState
90165

91166
type State = SipState;
167+
168+
#[inline(always)]
92169
fn State(k0: u64, k1: u64) -> State {
93170
SipState(k0, k1)
94171
}
95172

173+
#[inline(always)]
96174
fn default_state() -> State {
97175
State(0,0)
98176
}
@@ -109,6 +187,7 @@ struct SipState {
109187
mut ntail: uint; // how many bytes in tail are valid
110188
}
111189

190+
#[inline(always)]
112191
fn SipState(key0: u64, key1: u64) -> SipState {
113192
let state = SipState {
114193
k0 : key0,
@@ -129,6 +208,7 @@ fn SipState(key0: u64, key1: u64) -> SipState {
129208
impl &SipState : io::Writer {
130209

131210
// Methods for io::writer
211+
#[inline(always)]
132212
fn write(msg: &[const u8]) {
133213

134214
macro_rules! u8to64_le (
@@ -235,10 +315,12 @@ impl &SipState : io::Writer {
235315

236316
impl &SipState : Streaming {
237317

318+
#[inline(always)]
238319
fn input(buf: &[const u8]) {
239320
self.write(buf);
240321
}
241322

323+
#[inline(always)]
242324
fn result_u64() -> u64 {
243325
let mut v0 = self.v0;
244326
let mut v1 = self.v1;
@@ -269,7 +351,6 @@ impl &SipState : Streaming {
269351
return (v0 ^ v1 ^ v2 ^ v3);
270352
}
271353

272-
273354
fn result_bytes() -> ~[u8] {
274355
let h = self.result_u64();
275356
~[(h >> 0) as u8,
@@ -290,6 +371,7 @@ impl &SipState : Streaming {
290371
return s;
291372
}
292373

374+
#[inline(always)]
293375
fn reset() {
294376
self.length = 0;
295377
self.v0 = self.k0 ^ 0x736f6d6570736575;
@@ -385,7 +467,7 @@ fn test_siphash() {
385467
while t < 64 {
386468
debug!("siphash test %?", t);
387469
let vec = u8to64_le!(vecs[t], 0);
388-
let out = hash_bytes_keyed(buf, k0, k1);
470+
let out = buf.hash_keyed(k0, k1);
389471
debug!("got %?, expected %?", out, vec);
390472
assert vec == out;
391473

0 commit comments

Comments
 (0)