I'm trying to make a fast u8 to u64 array conversion. That is, take the u8 slice elements 8 by 8 and transform them into u64 big endian. The problem is that I'm collecting them into a Vec just so I can get the result and return if something is wrong. I didn't want to use allocations. I pass the result as a parameter to avoid allocations also.
#[inline]
fn convert<const N: usize, const N8: usize> (
bytes: [u8; N8],
) -> [u64; N]
{
assert_eq!(N.checked_mul(8), Some(N8));
if N == 0 { return []; }
let mut iter = bytes.array_chunks::<8>();
[(); N].map(|()| u64::from_be_bytes(*iter.next().unwrap()))
}
If you can't use .array_chunks() because you're not on nightly, you can use .chunks(8).map(|it: &[u8]| -> &[u8; 8] { it.try_into().unwrap() }) to polyfill it.
The branches, including the panicking branches, are removed once an explicit choice of N is given, since they're unreachable (provided you give correct values of N and N8).
You can achieve not having to bother writing the array lengths with a macro:
Assuming buffers have correct lengths and compiler is able to track this fact, ByteOrder::read_u64_into does not require any allocations and will compile down to a binary without panics (select "ASM" instead of "Run" to see generated assembly).