Start moving core::hash to support a Hash trait. Add to_bytes::IterBytes trait.
This commit is contained in:
parent
ab53819a2c
commit
a9619306a5
@ -15,6 +15,7 @@
|
||||
|
||||
import io::Writer;
|
||||
import io::WriterUtil;
|
||||
import to_bytes::IterBytes;
|
||||
|
||||
export Streaming, State;
|
||||
export default_state;
|
||||
@ -33,6 +34,21 @@
|
||||
export hash_u8;
|
||||
export hash_uint;
|
||||
|
||||
/// Types that can meaningfully be hashed should implement this.
|
||||
trait Hash {
|
||||
pure fn hash_keyed(k0: u64, k1: u64) -> u64;
|
||||
}
|
||||
|
||||
// When we have default methods, won't need this.
|
||||
trait HashUtil {
|
||||
pure fn hash() -> u64;
|
||||
}
|
||||
|
||||
impl <A: Hash> A: HashUtil {
|
||||
#[inline(always)]
|
||||
pure fn hash() -> u64 { self.hash_keyed(0,0) }
|
||||
}
|
||||
|
||||
/// Streaming hash-functions should implement this.
|
||||
trait Streaming {
|
||||
fn input((&[const u8]));
|
||||
@ -43,38 +59,97 @@ trait Streaming {
|
||||
fn reset();
|
||||
}
|
||||
|
||||
fn keyed(k0: u64, k1: u64, f: fn(s: &State)) -> u64 {
|
||||
let s = &State(k0, k1);
|
||||
f(s);
|
||||
s.result_u64()
|
||||
}
|
||||
|
||||
pure fn hash_bytes_keyed(buf: &[const u8], k0: u64, k1: u64) -> u64 {
|
||||
unchecked { keyed(k0, k1, |s| s.input(buf)) }
|
||||
}
|
||||
pure fn hash_str_keyed(s: &str, k0: u64, k1: u64) -> u64 {
|
||||
unsafe {
|
||||
do str::as_buf(s) |buf, len| {
|
||||
do vec::unsafe::form_slice(buf, len) |slice| {
|
||||
hash_bytes_keyed(slice, k0, k1)
|
||||
impl <A: IterBytes> A: Hash {
|
||||
#[inline(always)]
|
||||
pure fn hash_keyed(k0: u64, k1: u64) -> u64 {
|
||||
unchecked {
|
||||
let s = &State(k0, k1);
|
||||
for self.iter_le_bytes |bytes| {
|
||||
s.input(bytes);
|
||||
}
|
||||
s.result_u64()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// implementations
|
||||
|
||||
pure fn hash_keyed_2<A: IterBytes,
|
||||
B: IterBytes>(a: &A, b: &B,
|
||||
k0: u64, k1: u64) -> u64 {
|
||||
unchecked {
|
||||
let s = &State(k0, k1);
|
||||
for a.iter_le_bytes |bytes| { s.input(bytes); }
|
||||
for b.iter_le_bytes |bytes| { s.input(bytes); }
|
||||
s.result_u64()
|
||||
}
|
||||
}
|
||||
|
||||
pure fn hash_keyed_3<A: IterBytes,
|
||||
B: IterBytes,
|
||||
C: IterBytes>(a: &A, b: &B, c: &C,
|
||||
k0: u64, k1: u64) -> u64 {
|
||||
unchecked {
|
||||
let s = &State(k0, k1);
|
||||
for a.iter_le_bytes |bytes| { s.input(bytes); }
|
||||
for b.iter_le_bytes |bytes| { s.input(bytes); }
|
||||
for c.iter_le_bytes |bytes| { s.input(bytes); }
|
||||
s.result_u64()
|
||||
}
|
||||
}
|
||||
|
||||
pure fn hash_keyed_4<A: IterBytes,
|
||||
B: IterBytes,
|
||||
C: IterBytes,
|
||||
D: IterBytes>(a: &A, b: &B, c: &C, d: &D,
|
||||
k0: u64, k1: u64) -> u64 {
|
||||
unchecked {
|
||||
let s = &State(k0, k1);
|
||||
for a.iter_le_bytes |bytes| { s.input(bytes); }
|
||||
for b.iter_le_bytes |bytes| { s.input(bytes); }
|
||||
for c.iter_le_bytes |bytes| { s.input(bytes); }
|
||||
for d.iter_le_bytes |bytes| { s.input(bytes); }
|
||||
s.result_u64()
|
||||
}
|
||||
}
|
||||
|
||||
pure fn hash_keyed_5<A: IterBytes,
|
||||
B: IterBytes,
|
||||
C: IterBytes,
|
||||
D: IterBytes,
|
||||
E: IterBytes>(a: &A, b: &B, c: &C, d: &D, e: &E,
|
||||
k0: u64, k1: u64) -> u64 {
|
||||
unchecked {
|
||||
let s = &State(k0, k1);
|
||||
for a.iter_le_bytes |bytes| { s.input(bytes); }
|
||||
for b.iter_le_bytes |bytes| { s.input(bytes); }
|
||||
for c.iter_le_bytes |bytes| { s.input(bytes); }
|
||||
for d.iter_le_bytes |bytes| { s.input(bytes); }
|
||||
for e.iter_le_bytes |bytes| { s.input(bytes); }
|
||||
s.result_u64()
|
||||
}
|
||||
}
|
||||
|
||||
pure fn hash_bytes_keyed(val: &[const u8], k0: u64, k1: u64) -> u64 {
|
||||
val.hash_keyed(k0, k1)
|
||||
}
|
||||
pure fn hash_str_keyed(val: &str, k0: u64, k1: u64) -> u64 {
|
||||
val.hash_keyed(k0, k1)
|
||||
}
|
||||
pure fn hash_u64_keyed(val: u64, k0: u64, k1: u64) -> u64 {
|
||||
unchecked { keyed(k0, k1, |s| s.write_le_u64(val)) }
|
||||
val.hash_keyed(k0, k1)
|
||||
}
|
||||
pure fn hash_u32_keyed(val: u32, k0: u64, k1: u64) -> u64 {
|
||||
unchecked { keyed(k0, k1, |s| s.write_le_u32(val)) }
|
||||
val.hash_keyed(k0, k1)
|
||||
}
|
||||
pure fn hash_u16_keyed(val: u16, k0: u64, k1: u64) -> u64 {
|
||||
unchecked { keyed(k0, k1, |s| s.write_le_u16(val)) }
|
||||
val.hash_keyed(k0, k1)
|
||||
}
|
||||
pure fn hash_u8_keyed(val: u8, k0: u64, k1: u64) -> u64 {
|
||||
unchecked { keyed(k0, k1, |s| s.write_u8(val)) }
|
||||
val.hash_keyed(k0, k1)
|
||||
}
|
||||
pure fn hash_uint_keyed(val: uint, k0: u64, k1: u64) -> u64 {
|
||||
unchecked { keyed(k0, k1, |s| s.write_le_uint(val)) }
|
||||
val.hash_keyed(k0, k1)
|
||||
}
|
||||
|
||||
pure fn hash_bytes(val: &[const u8]) -> u64 { hash_bytes_keyed(val, 0, 0) }
|
||||
@ -89,10 +164,13 @@ fn keyed(k0: u64, k1: u64, f: fn(s: &State)) -> u64 {
|
||||
// Implement State as SipState
|
||||
|
||||
type State = SipState;
|
||||
|
||||
#[inline(always)]
|
||||
fn State(k0: u64, k1: u64) -> State {
|
||||
SipState(k0, k1)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn default_state() -> State {
|
||||
State(0,0)
|
||||
}
|
||||
@ -109,6 +187,7 @@ struct SipState {
|
||||
mut ntail: uint; // how many bytes in tail are valid
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn SipState(key0: u64, key1: u64) -> SipState {
|
||||
let state = SipState {
|
||||
k0 : key0,
|
||||
@ -129,6 +208,7 @@ fn SipState(key0: u64, key1: u64) -> SipState {
|
||||
impl &SipState : io::Writer {
|
||||
|
||||
// Methods for io::writer
|
||||
#[inline(always)]
|
||||
fn write(msg: &[const u8]) {
|
||||
|
||||
macro_rules! u8to64_le (
|
||||
@ -235,10 +315,12 @@ fn get_type() -> io::WriterType {
|
||||
|
||||
impl &SipState : Streaming {
|
||||
|
||||
#[inline(always)]
|
||||
fn input(buf: &[const u8]) {
|
||||
self.write(buf);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn result_u64() -> u64 {
|
||||
let mut v0 = self.v0;
|
||||
let mut v1 = self.v1;
|
||||
@ -269,7 +351,6 @@ fn result_u64() -> u64 {
|
||||
return (v0 ^ v1 ^ v2 ^ v3);
|
||||
}
|
||||
|
||||
|
||||
fn result_bytes() -> ~[u8] {
|
||||
let h = self.result_u64();
|
||||
~[(h >> 0) as u8,
|
||||
@ -290,6 +371,7 @@ fn result_str() -> ~str {
|
||||
return s;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn reset() {
|
||||
self.length = 0;
|
||||
self.v0 = self.k0 ^ 0x736f6d6570736575;
|
||||
@ -385,7 +467,7 @@ fn to_hex_str(r: &[u8]/8) -> ~str {
|
||||
while t < 64 {
|
||||
debug!("siphash test %?", t);
|
||||
let vec = u8to64_le!(vecs[t], 0);
|
||||
let out = hash_bytes_keyed(buf, k0, k1);
|
||||
let out = buf.hash_keyed(k0, k1);
|
||||
debug!("got %?, expected %?", out, vec);
|
||||
assert vec == out;
|
||||
|
||||
|
@ -2,22 +2,314 @@
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
import io::Writer;
|
||||
|
||||
type Cb = fn(buf: &[const u8]) -> bool;
|
||||
|
||||
trait IterBytes {
|
||||
fn iter_le_bytes(f: Cb);
|
||||
fn iter_be_bytes(f: Cb);
|
||||
}
|
||||
|
||||
impl u8: IterBytes {
|
||||
#[inline(always)]
|
||||
fn iter_le_bytes(f: Cb) {
|
||||
f([
|
||||
self,
|
||||
]);
|
||||
}
|
||||
#[inline(always)]
|
||||
fn iter_be_bytes(f: Cb) {
|
||||
f([
|
||||
self as u8
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
impl u16: IterBytes {
|
||||
#[inline(always)]
|
||||
fn iter_le_bytes(f: Cb) {
|
||||
f([
|
||||
self as u8,
|
||||
(self >> 8) as u8
|
||||
]);
|
||||
}
|
||||
#[inline(always)]
|
||||
fn iter_be_bytes(f: Cb) {
|
||||
f([
|
||||
(self >> 8) as u8,
|
||||
self as u8
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
impl u32: IterBytes {
|
||||
#[inline(always)]
|
||||
fn iter_le_bytes(f: Cb) {
|
||||
f([
|
||||
self as u8,
|
||||
(self >> 8) as u8,
|
||||
(self >> 16) as u8,
|
||||
(self >> 24) as u8,
|
||||
]);
|
||||
}
|
||||
#[inline(always)]
|
||||
fn iter_be_bytes(f: Cb) {
|
||||
f([
|
||||
(self >> 24) as u8,
|
||||
(self >> 16) as u8,
|
||||
(self >> 8) as u8,
|
||||
self as u8
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
impl u64: IterBytes {
|
||||
#[inline(always)]
|
||||
fn iter_le_bytes(f: Cb) {
|
||||
f([
|
||||
self as u8,
|
||||
(self >> 8) as u8,
|
||||
(self >> 16) as u8,
|
||||
(self >> 24) as u8,
|
||||
(self >> 32) as u8,
|
||||
(self >> 40) as u8,
|
||||
(self >> 48) as u8,
|
||||
(self >> 56) as u8
|
||||
]);
|
||||
}
|
||||
#[inline(always)]
|
||||
fn iter_be_bytes(f: Cb) {
|
||||
f([
|
||||
(self >> 56) as u8,
|
||||
(self >> 48) as u8,
|
||||
(self >> 40) as u8,
|
||||
(self >> 32) as u8,
|
||||
(self >> 24) as u8,
|
||||
(self >> 16) as u8,
|
||||
(self >> 8) as u8,
|
||||
self as u8
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
impl i8: IterBytes {
|
||||
#[inline(always)]
|
||||
fn iter_le_bytes(f: Cb) { (self as u8).iter_le_bytes(f) }
|
||||
#[inline(always)]
|
||||
fn iter_be_bytes(f: Cb) { (self as u8).iter_be_bytes(f) }
|
||||
}
|
||||
|
||||
impl i16: IterBytes {
|
||||
#[inline(always)]
|
||||
fn iter_le_bytes(f: Cb) { (self as u16).iter_le_bytes(f) }
|
||||
#[inline(always)]
|
||||
fn iter_be_bytes(f: Cb) { (self as u16).iter_be_bytes(f) }
|
||||
}
|
||||
|
||||
impl i32: IterBytes {
|
||||
#[inline(always)]
|
||||
fn iter_le_bytes(f: Cb) { (self as u32).iter_le_bytes(f) }
|
||||
#[inline(always)]
|
||||
fn iter_be_bytes(f: Cb) { (self as u32).iter_be_bytes(f) }
|
||||
}
|
||||
|
||||
impl i64: IterBytes {
|
||||
#[inline(always)]
|
||||
fn iter_le_bytes(f: Cb) { (self as u64).iter_le_bytes(f) }
|
||||
#[inline(always)]
|
||||
fn iter_be_bytes(f: Cb) { (self as u64).iter_be_bytes(f) }
|
||||
}
|
||||
|
||||
#[cfg(target_word_size = "32")]
|
||||
impl uint: IterBytes {
|
||||
#[inline(always)]
|
||||
fn iter_le_bytes(f: Cb) { (self as u32).iter_le_bytes(f) }
|
||||
#[inline(always)]
|
||||
fn iter_be_bytes(f: Cb) { (self as u32).iter_be_bytes(f) }
|
||||
}
|
||||
|
||||
#[cfg(target_word_size = "64")]
|
||||
impl uint: IterBytes {
|
||||
#[inline(always)]
|
||||
fn iter_le_bytes(f: Cb) { (self as u64).iter_le_bytes(f) }
|
||||
#[inline(always)]
|
||||
fn iter_be_bytes(f: Cb) { (self as u64).iter_be_bytes(f) }
|
||||
}
|
||||
|
||||
impl int: IterBytes {
|
||||
#[inline(always)]
|
||||
fn iter_le_bytes(f: Cb) { (self as uint).iter_le_bytes(f) }
|
||||
#[inline(always)]
|
||||
fn iter_be_bytes(f: Cb) { (self as uint).iter_be_bytes(f) }
|
||||
}
|
||||
|
||||
impl ~[const u8]: IterBytes {
|
||||
#[inline(always)]
|
||||
fn iter_le_bytes(f: Cb) { f(self); }
|
||||
#[inline(always)]
|
||||
fn iter_be_bytes(f: Cb) { f(self); }
|
||||
}
|
||||
|
||||
impl @[const u8]: IterBytes {
|
||||
#[inline(always)]
|
||||
fn iter_le_bytes(f: Cb) { f(self); }
|
||||
#[inline(always)]
|
||||
fn iter_be_bytes(f: Cb) { f(self); }
|
||||
}
|
||||
|
||||
impl<A: IterBytes> &[const A]: IterBytes {
|
||||
#[inline(always)]
|
||||
fn iter_le_bytes(f: Cb) {
|
||||
for self.each |elt| {
|
||||
do elt.iter_le_bytes |bytes| {
|
||||
f(bytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
#[inline(always)]
|
||||
fn iter_be_bytes(f: Cb) {
|
||||
for self.each |elt| {
|
||||
do elt.iter_be_bytes |bytes| {
|
||||
f(bytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn iter_le_bytes_2<A: IterBytes, B: IterBytes>(a: &A, b: &B, f: Cb) {
|
||||
let mut flag = true;
|
||||
a.iter_le_bytes(|bytes| {flag = f(bytes); flag});
|
||||
if !flag { return; }
|
||||
b.iter_le_bytes(|bytes| {flag = f(bytes); flag});
|
||||
}
|
||||
|
||||
fn iter_be_bytes_2<A: IterBytes, B: IterBytes>(a: &A, b: &B, f: Cb) {
|
||||
let mut flag = true;
|
||||
a.iter_be_bytes(|bytes| {flag = f(bytes); flag});
|
||||
if !flag { return; }
|
||||
b.iter_be_bytes(|bytes| {flag = f(bytes); flag});
|
||||
}
|
||||
|
||||
fn iter_le_bytes_3<A: IterBytes,
|
||||
B: IterBytes,
|
||||
C: IterBytes>(a: &A, b: &B, c: &C, f: Cb) {
|
||||
let mut flag = true;
|
||||
a.iter_le_bytes(|bytes| {flag = f(bytes); flag});
|
||||
if !flag { return; }
|
||||
b.iter_le_bytes(|bytes| { flag = f(bytes); flag});
|
||||
if !flag { return; }
|
||||
c.iter_le_bytes(|bytes| {flag = f(bytes); flag});
|
||||
}
|
||||
|
||||
fn iter_be_bytes_3<A: IterBytes,
|
||||
B: IterBytes,
|
||||
C: IterBytes>(a: &A, b: &B, c: &C, f: Cb) {
|
||||
let mut flag = true;
|
||||
a.iter_be_bytes(|bytes| {flag = f(bytes); flag});
|
||||
if !flag { return; }
|
||||
b.iter_be_bytes(|bytes| {flag = f(bytes); flag});
|
||||
if !flag { return; }
|
||||
c.iter_be_bytes(|bytes| {flag = f(bytes); flag});
|
||||
}
|
||||
|
||||
impl &str: IterBytes {
|
||||
#[inline(always)]
|
||||
fn iter_le_bytes(f: Cb) {
|
||||
do str::byte_slice(self) |bytes| {
|
||||
f(bytes);
|
||||
}
|
||||
}
|
||||
#[inline(always)]
|
||||
fn iter_be_bytes(f: Cb) {
|
||||
do str::byte_slice(self) |bytes| {
|
||||
f(bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ~str: IterBytes {
|
||||
#[inline(always)]
|
||||
fn iter_le_bytes(f: Cb) {
|
||||
do str::byte_slice(self) |bytes| {
|
||||
f(bytes);
|
||||
}
|
||||
}
|
||||
#[inline(always)]
|
||||
fn iter_be_bytes(f: Cb) {
|
||||
do str::byte_slice(self) |bytes| {
|
||||
f(bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl @str: IterBytes {
|
||||
#[inline(always)]
|
||||
fn iter_le_bytes(f: Cb) {
|
||||
do str::byte_slice(self) |bytes| {
|
||||
f(bytes);
|
||||
}
|
||||
}
|
||||
#[inline(always)]
|
||||
fn iter_be_bytes(f: Cb) {
|
||||
do str::byte_slice(self) |bytes| {
|
||||
f(bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<A: IterBytes> &A: IterBytes {
|
||||
#[inline(always)]
|
||||
fn iter_le_bytes(f: Cb) {
|
||||
(*self).iter_le_bytes(f);
|
||||
}
|
||||
#[inline(always)]
|
||||
fn iter_be_bytes(f: Cb) {
|
||||
(*self).iter_be_bytes(f);
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: IterBytes> @A: IterBytes {
|
||||
#[inline(always)]
|
||||
fn iter_le_bytes(f: Cb) {
|
||||
(*self).iter_le_bytes(f);
|
||||
}
|
||||
#[inline(always)]
|
||||
fn iter_be_bytes(f: Cb) {
|
||||
(*self).iter_be_bytes(f);
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: IterBytes> ~A: IterBytes {
|
||||
#[inline(always)]
|
||||
fn iter_le_bytes(f: Cb) {
|
||||
(*self).iter_le_bytes(f);
|
||||
}
|
||||
#[inline(always)]
|
||||
fn iter_be_bytes(f: Cb) {
|
||||
(*self).iter_be_bytes(f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
trait ToBytes {
|
||||
fn to_bytes() -> ~[u8];
|
||||
fn to_le_bytes() -> ~[u8];
|
||||
fn to_be_bytes() -> ~[u8];
|
||||
}
|
||||
|
||||
impl ~[u8]: ToBytes {
|
||||
fn to_bytes() -> ~[u8] { copy self }
|
||||
}
|
||||
impl<A: IterBytes> A: ToBytes {
|
||||
fn to_le_bytes() -> ~[u8] {
|
||||
let buf = io::mem_buffer();
|
||||
for self.iter_le_bytes |bytes| {
|
||||
buf.write(bytes)
|
||||
}
|
||||
io::mem_buffer_buf(buf)
|
||||
}
|
||||
fn to_be_bytes() -> ~[u8] {
|
||||
let buf = io::mem_buffer();
|
||||
for self.iter_be_bytes |bytes| {
|
||||
buf.write(bytes)
|
||||
}
|
||||
io::mem_buffer_buf(buf)
|
||||
}
|
||||
|
||||
impl @~[u8]: ToBytes {
|
||||
fn to_bytes() -> ~[u8] { copy *self }
|
||||
}
|
||||
|
||||
impl ~str: ToBytes {
|
||||
fn to_bytes() -> ~[u8] { str::to_bytes(self) }
|
||||
}
|
||||
|
||||
impl @(~str): ToBytes {
|
||||
fn to_bytes() -> ~[u8] { str::to_bytes(*self) }
|
||||
}
|
||||
|
@ -1168,7 +1168,7 @@ fn reverse<T>(v: ~[mut T]) {
|
||||
* Return true to continue, false to break.
|
||||
*/
|
||||
#[inline(always)]
|
||||
pure fn each<T>(v: &[T], f: fn(T) -> bool) {
|
||||
pure fn each<T>(v: &[const T], f: fn(T) -> bool) {
|
||||
do vec::as_buf(v) |p, n| {
|
||||
let mut n = n;
|
||||
let mut p = p;
|
||||
@ -1206,7 +1206,7 @@ fn reverse<T>(v: ~[mut T]) {
|
||||
* Return true to continue, false to break.
|
||||
*/
|
||||
#[inline(always)]
|
||||
pure fn eachi<T>(v: &[T], f: fn(uint, T) -> bool) {
|
||||
pure fn eachi<T>(v: &[const T], f: fn(uint, T) -> bool) {
|
||||
do vec::as_buf(v) |p, n| {
|
||||
let mut i = 0u;
|
||||
let mut p = p;
|
||||
@ -1916,12 +1916,12 @@ fn memmove(dst: &[mut u8], src: &[const u8], count: uint) {
|
||||
// This cannot be used with iter-trait.rs because of the region pointer
|
||||
// required in the slice.
|
||||
|
||||
impl<A> &[A]: iter::BaseIter<A> {
|
||||
impl<A> &[const A]: iter::BaseIter<A> {
|
||||
pure fn each(blk: fn(A) -> bool) { each(self, blk) }
|
||||
pure fn size_hint() -> Option<uint> { Some(len(self)) }
|
||||
}
|
||||
|
||||
impl<A> &[A]: iter::ExtendedIter<A> {
|
||||
impl<A> &[const A]: iter::ExtendedIter<A> {
|
||||
pure fn eachi(blk: fn(uint, A) -> bool) { iter::eachi(self, blk) }
|
||||
pure fn all(blk: fn(A) -> bool) -> bool { iter::all(self, blk) }
|
||||
pure fn any(blk: fn(A) -> bool) -> bool { iter::any(self, blk) }
|
||||
|
Loading…
Reference in New Issue
Block a user