This could be reduced to just my_u16_slice.iter().copied().flat_map(u16::to_ne_bytes) if IntoIterator were implemented for arrays, but that's not available yet unfortunately.
641 | for b in my_u16_slice.iter().copied().flat_map(|v| v.to_ne_bytes().iter().copied()) {
| ---------------^^^^^^^^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| temporary value created here
I rarely suggest using an unsafe function, but it seems <[u16]>::align_to::<u8>() would be appropriate here, as u8 and u16 both are copy without any niche/invalid values, and u16 has alignment larger than that of 8.
So my_u16_slice.align_to::<u8>().1 could work, like this.
Ah, whoops, sorry about that—I should've checked my intuition on the playground first!
Try my_u16_slice.iter().flat_map(|&v| std::array::IntoIter::new(v.to_ne_bytes())). This lets you use IntoIterator for arrays in a slightly clunky indirect form while the actual impl is still unstable.
I agree that the nicest solution would be something that casts it to &[u8] and iterates over that. Though, I prefer a method like this one over align_to to be honest.
fn as_u8_slice(slice: &[u16]) -> &[u8] {
let len = 2*slice.len();
let ptr = slice.as_ptr().cast::<u8>();
unsafe {
std::slice::from_raw_parts(ptr, len)
}
}
The zerocopy crate can also do it without unsafe code. Here you can just import the AsBytes trait and call .as_bytes() on your u16 slice.
The method may make the middle slice the greatest length possible for a given type and input slice, but only your algorithm's performance should depend on that, not its correctness. It is permissible for all of the input data to be returned as the prefix or suffix slice.
Consider looking at it from a slightly different direction, and writing the u16s into pairs of bytes instead of splitting the u16s into individual bytes:
Make sure you don’t confuse something working on nightly with #![feature(…)] flags with something working on nightly without #![feature(…)] flags. This is working without any feature flags. The IntoIterator implementation for arrays was recently implemented and also stabilized in #84147 and is thus (most likely) going to arrive in stable with Rust 1.53 on June 17th 2021.
Edit: Oh, wait you weren’t even talking about the array IntoIterator? I should’ve probably read more carefully what you wrote there.
That's because with chunks_mut the last slice may have less elements than the others, thus that try_into may actually fail. chunks_exact_mut however solves this problem:
I have to think more about how you interpreted the statement. This said, when I used align_to to build simd vectors, the stride was aligned as “requested”, in this case u8. AFAIK having read how the algorithm “came to be”, that’s guaranteed. What’s up in the air is the length of the three blocks (prefix, middle and suffix). Unsafe, performance may vary, but no UB.