use clone::Clone;
use container::Container;
use default::Default;
+use int;
use io::{IoResult, Writer};
use iter::Iterator;
use result::Ok;
use slice::ImmutableVector;
+use uint;
use super::{Hash, Hasher};
v1: u64,
v2: u64,
v3: u64,
- tail: [u8, ..8], // unprocessed bytes
+ tail: u64, // unprocessed bytes le
ntail: uint, // how many bytes in tail are valid
}
$buf[4+$i] as u64 << 32 |
$buf[5+$i] as u64 << 40 |
$buf[6+$i] as u64 << 48 |
- $buf[7+$i] as u64 << 56)
+ $buf[7+$i] as u64 << 56);
+ ($buf:expr, $i:expr, $len:expr) =>
+ ({
+ let mut t = 0;
+ let mut out = 0u64;
+ while t < $len {
+ out |= $buf[t+$i] as u64 << t*8;
+ t += 1;
+ }
+ out
+ });
)
macro_rules! rotl (
v1: 0,
v2: 0,
v3: 0,
- tail: [ 0, 0, 0, 0, 0, 0, 0, 0 ],
+ tail: 0,
ntail: 0,
};
state.reset();
let mut v2 = self.v2;
let mut v3 = self.v3;
- let mut b : u64 = (self.length as u64 & 0xff) << 56;
-
- if self.ntail > 0 { b |= self.tail[0] as u64 << 0; }
- if self.ntail > 1 { b |= self.tail[1] as u64 << 8; }
- if self.ntail > 2 { b |= self.tail[2] as u64 << 16; }
- if self.ntail > 3 { b |= self.tail[3] as u64 << 24; }
- if self.ntail > 4 { b |= self.tail[4] as u64 << 32; }
- if self.ntail > 5 { b |= self.tail[5] as u64 << 40; }
- if self.ntail > 6 { b |= self.tail[6] as u64 << 48; }
+ let b: u64 = ((self.length as u64 & 0xff) << 56) | self.tail;
v3 ^= b;
compress!(v0, v1, v2, v3);
v0 ^ v1 ^ v2 ^ v3
}
+
+ #[inline]
+ fn write_le(&mut self, n: u64, size: uint) {
+ self.tail |= n << 8*self.ntail;
+ self.ntail += size;
+
+ if self.ntail >= 8 {
+ let m = self.tail;
+
+ self.v3 ^= m;
+ compress!(self.v0, self.v1, self.v2, self.v3);
+ compress!(self.v0, self.v1, self.v2, self.v3);
+ self.v0 ^= m;
+
+ self.ntail -= 8;
+ if self.ntail == 0 {
+ self.tail = 0;
+ } else {
+ self.tail = n >> 64 - 8*self.ntail;
+ }
+ }
+ }
}
+macro_rules! make_write_le(
+ ($this:expr, $n:expr, $size:expr) => ({
+ $this.write_le($n as u64, $size);
+ $this.length += $size;
+ Ok(())
+ })
+)
+
impl Writer for SipState {
#[inline]
fn write(&mut self, msg: &[u8]) -> IoResult<()> {
if self.ntail != 0 {
needed = 8 - self.ntail;
-
if length < needed {
- let mut t = 0;
- while t < length {
- self.tail[self.ntail+t] = msg[t];
- t += 1;
- }
+ self.tail |= u8to64_le!(msg, 0, length) << 8*self.ntail;
self.ntail += length;
return Ok(());
}
- let mut t = 0;
- while t < needed {
- self.tail[self.ntail+t] = msg[t];
- t += 1;
- }
-
- let m = u8to64_le!(self.tail, 0);
+ let m = self.tail | u8to64_le!(msg, 0, needed) << 8*self.ntail;
self.v3 ^= m;
compress!(self.v0, self.v1, self.v2, self.v3);
i += 8;
}
- let mut t = 0u;
- while t < left {
- self.tail[t] = msg[i+t];
- t += 1
- }
+ self.tail = u8to64_le!(msg, i, left);
self.ntail = left;
Ok(())
}
+
+ #[inline]
+ fn write_u8(&mut self, n: u8) -> IoResult<()> {
+ make_write_le!(self, n, 1)
+ }
+
+ #[inline]
+ fn write_le_u16(&mut self, n: u16) -> IoResult<()> {
+ make_write_le!(self, n, 2)
+ }
+
+ #[inline]
+ fn write_le_u32(&mut self, n: u32) -> IoResult<()> {
+ make_write_le!(self, n, 4)
+ }
+
+ #[inline]
+ fn write_le_u64(&mut self, n: u64) -> IoResult<()> {
+ make_write_le!(self, n, 8)
+ }
+
+ #[inline]
+ fn write_le_uint(&mut self, n: uint) -> IoResult<()> {
+ make_write_le!(self, n, uint::BYTES)
+ }
+
+ #[inline]
+ fn write_i8(&mut self, n: i8) -> IoResult<()> {
+ make_write_le!(self, n, 1)
+ }
+
+ #[inline]
+ fn write_le_i16(&mut self, n: i16) -> IoResult<()> {
+ make_write_le!(self, n, 2)
+ }
+
+ #[inline]
+ fn write_le_i32(&mut self, n: i32) -> IoResult<()> {
+ make_write_le!(self, n, 4)
+ }
+
+ #[inline]
+ fn write_le_i64(&mut self, n: i64) -> IoResult<()> {
+ make_write_le!(self, n, 8)
+ }
+
+ #[inline]
+ fn write_le_int(&mut self, n: int) -> IoResult<()> {
+ make_write_le!(self, n, int::BYTES)
+ }
+
}
impl Clone for SipState {
state.result()
}
+
+
#[cfg(test)]
mod tests {
extern crate test;
}
#[bench]
- fn bench_str(b: &mut Bencher) {
+ fn bench_str_under_8_bytes(b: &mut Bencher) {
let s = "foo";
b.iter(|| {
assert_eq!(hash(&s), 16262950014981195938);
})
}
+ #[bench]
+ fn bench_str_of_8_bytes(b: &mut Bencher) {
+ let s = "foobar78";
+ b.iter(|| {
+ assert_eq!(hash(&s), 4898293253460910787);
+ })
+ }
+
+ #[bench]
+ fn bench_str_over_8_bytes(b: &mut Bencher) {
+ let s = "foobarbaz0";
+ b.iter(|| {
+ assert_eq!(hash(&s), 10581415515220175264);
+ })
+ }
+
+ #[bench]
+ fn bench_long_str(b: &mut Bencher) {
+ let s = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor \
+incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud \
+exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute \
+irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla \
+pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui \
+officia deserunt mollit anim id est laborum.";
+ b.iter(|| {
+ assert_eq!(hash(&s), 17717065544121360093);
+ })
+ }
+
+ #[bench]
+ fn bench_u64(b: &mut Bencher) {
+ let u = 16262950014981195938u64;
+ b.iter(|| {
+ assert_eq!(hash(&u), 5254097107239593357);
+ })
+ }
+
+ #[deriving(Hash)]
struct Compound {
x: u8,
- y: u16,
+ y: u64,
z: ~str,
}
- impl<S: Writer> Hash<S> for Compound {
- #[inline]
- fn hash(&self, state: &mut S) {
- self.x.hash(state);
- self.y.hash(state);
- self.z.hash(state);
- }
- }
-
#[bench]
fn bench_compound_1(b: &mut Bencher) {
let compound = Compound {
z: ~"foobarbaz",
};
b.iter(|| {
- assert_eq!(hash(&compound), 3581836382593270478);
+ assert_eq!(hash(&compound), 15783192367317361799);
})
}
}