Skip to content

Commit 9aea154

Browse files
committedFeb 12, 2020
Improve u8to64_le.
This makes it faster and also changes it to a safe function. (Thanks to Michael Woerister for the suggestion.) `load_int_le!` is also no longer necessary.
1 parent f8a0286 commit 9aea154

File tree

1 file changed

+12
-41
lines changed

1 file changed

+12
-41
lines changed
 

‎src/librustc_data_structures/sip128.rs

+12-41
Original file line numberDiff line numberDiff line change
@@ -51,46 +51,17 @@ macro_rules! compress {
5151
}};
5252
}
5353

54-
/// Loads an integer of the desired type from a byte stream, in LE order. Uses
55-
/// `copy_nonoverlapping` to let the compiler generate the most efficient way
56-
/// to load it from a possibly unaligned address.
57-
///
58-
/// Unsafe because: unchecked indexing at i..i+size_of(int_ty)
59-
macro_rules! load_int_le {
60-
($buf:expr, $i:expr, $int_ty:ident) => {{
61-
debug_assert!($i + mem::size_of::<$int_ty>() <= $buf.len());
62-
let mut data = 0 as $int_ty;
63-
ptr::copy_nonoverlapping(
64-
$buf.get_unchecked($i),
65-
&mut data as *mut _ as *mut u8,
66-
mem::size_of::<$int_ty>(),
67-
);
68-
data.to_le()
69-
}};
70-
}
71-
72-
/// Loads an u64 using up to 7 bytes of a byte slice.
73-
///
74-
/// Unsafe because: unchecked indexing at start..start+len
54+
/// Loads up to 8 bytes from a byte-slice into a little-endian u64.
7555
#[inline]
76-
unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 {
77-
debug_assert!(len < 8);
78-
let mut i = 0; // current byte index (from LSB) in the output u64
79-
let mut out = 0;
80-
if i + 3 < len {
81-
out = u64::from(load_int_le!(buf, start + i, u32));
82-
i += 4;
83-
}
84-
if i + 1 < len {
85-
out |= u64::from(load_int_le!(buf, start + i, u16)) << (i * 8);
86-
i += 2
87-
}
88-
if i < len {
89-
out |= u64::from(*buf.get_unchecked(start + i)) << (i * 8);
90-
i += 1;
56+
fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 {
57+
assert!(len <= 8 && start + len <= buf.len());
58+
59+
let mut out = 0u64;
60+
unsafe {
61+
let out_ptr = &mut out as *mut _ as *mut u8;
62+
ptr::copy_nonoverlapping(buf.as_ptr().offset(start as isize), out_ptr, len);
9163
}
92-
debug_assert_eq!(i, len);
93-
out
64+
out.to_le()
9465
}
9566

9667
impl SipHasher128 {
@@ -272,7 +243,7 @@ impl Hasher for SipHasher128 {
272243

273244
if self.ntail != 0 {
274245
needed = 8 - self.ntail;
275-
self.tail |= unsafe { u8to64_le(msg, 0, cmp::min(length, needed)) } << (8 * self.ntail);
246+
self.tail |= u8to64_le(msg, 0, cmp::min(length, needed)) << (8 * self.ntail);
276247
if length < needed {
277248
self.ntail += length;
278249
return;
@@ -290,7 +261,7 @@ impl Hasher for SipHasher128 {
290261

291262
let mut i = needed;
292263
while i < len - left {
293-
let mi = unsafe { load_int_le!(msg, i, u64) };
264+
let mi = u8to64_le(msg, i, 8);
294265

295266
self.state.v3 ^= mi;
296267
Sip24Rounds::c_rounds(&mut self.state);
@@ -299,7 +270,7 @@ impl Hasher for SipHasher128 {
299270
i += 8;
300271
}
301272

302-
self.tail = unsafe { u8to64_le(msg, i, left) };
273+
self.tail = u8to64_le(msg, i, left);
303274
self.ntail = left;
304275
}
305276

0 commit comments

Comments
 (0)
Please sign in to comment.