Can you guys find a way to get rid of the unsafe block while still keeping the function panic-free?
fn sha1(data: &[u8]) -> [u8; 20] {
let mut h = [0x67452301_u32, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0];
let mut chunk_buf = [0; 64];
let len_padding = (8 * data.len() as u64).to_be_bytes();
let mut empty_chunk = [0; 64];
empty_chunk[56..].copy_from_slice(&len_padding);
for i in (0..data.len() + 9).step_by(64) {
let chunk = match data.len().checked_sub(i) {
// SAFETY: data.len() >= i + 64, so this can't be out of bounds
// The optimizer is not smart enough to elide the bounds check
Some(64..) => unsafe { data.get_unchecked(i..i + 64) },
Some(chunk_len) => {
chunk_buf[..chunk_len].copy_from_slice(&data[i..data.len()]);
chunk_buf[chunk_len] = 0x80;
if chunk_len < 56 {
chunk_buf[56..].copy_from_slice(&len_padding);
}
&chunk_buf
},
None => &empty_chunk
};
let mut w = [0; 80];
for j in 0..16 {
w[j] = u32::from_be_bytes(chunk[j * 4..j * 4 + 4].try_into().unwrap());
}
for j in 16..80 {
w[j] = (w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16]).rotate_left(1);
}
let [mut a, mut b, mut c, mut d, mut e] = h;
for j in 0..20 {
let temp = a.rotate_left(5)
.wrapping_add(e)
.wrapping_add(w[j])
.wrapping_add(0x5A827999)
.wrapping_add(b & c | !b & d);
e = d;
d = c;
c = b.rotate_left(30);
b = a;
a = temp;
}