diff --git a/src/libcore/hash.rs b/src/libcore/hash.rs index da684c8fab5..0e9c9110c8e 100644 --- a/src/libcore/hash.rs +++ b/src/libcore/hash.rs @@ -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_u16; 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: 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: 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: &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: &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: &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: &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 @@ pure fn hash_uint(val: uint) -> u64 { hash_uint_keyed(val, 0, 0) } // 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 @@ impl &SipState : io::Writer { 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 @@ impl &SipState : Streaming { return (v0 ^ v1 ^ v2 ^ v3); } - fn result_bytes() -> ~[u8] { let h = self.result_u64(); ~[(h >> 0) as u8, @@ -290,6 +371,7 @@ impl &SipState : Streaming { return s; } + #[inline(always)] fn reset() { self.length = 0; self.v0 = self.k0 ^ 0x736f6d6570736575; @@ -385,7 +467,7 @@ fn test_siphash() { 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; diff --git a/src/libcore/to_bytes.rs b/src/libcore/to_bytes.rs index 6a5558e0236..f4305a74917 100644 --- a/src/libcore/to_bytes.rs +++ b/src/libcore/to_bytes.rs @@ -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 &[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: &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: &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: &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: &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 { + #[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 { + #[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 { + #[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: 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) } } diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index baf6c7c8601..1533b07861c 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -1168,7 +1168,7 @@ pure fn iter_between(v: &[T], start: uint, end: uint, f: fn(T)) { * Return true to continue, false to break. */ #[inline(always)] -pure fn each(v: &[T], f: fn(T) -> bool) { +pure fn each(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 @@ pure fn each_mut(v: &[mut T], f: fn(elem: &mut T) -> bool) { * Return true to continue, false to break. */ #[inline(always)] -pure fn eachi(v: &[T], f: fn(uint, T) -> bool) { +pure fn eachi(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 @@ mod u8 { // This cannot be used with iter-trait.rs because of the region pointer // required in the slice. -impl &[A]: iter::BaseIter { +impl &[const A]: iter::BaseIter { pure fn each(blk: fn(A) -> bool) { each(self, blk) } pure fn size_hint() -> Option { Some(len(self)) } } -impl &[A]: iter::ExtendedIter { +impl &[const A]: iter::ExtendedIter { 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) }