Is `array::from_fn`+`bytemuck::must_cast_ref` idiomatic?

I have this code,

fn load_foobunch(arr: &[u8; std::mem::size_of::<[Foo; 42]>()]) -> [Foo; 42] {
    core::array::from_fn({
        let view: &[[u8; std::mem::size_of::<Foo>()]; 42] = bytemuck::must_cast_ref(&arr);
        |i| crate::construct_one_foo(&view[i])
    });
}

which builds a new array of Foo (which is repr(C) but requires some masking and validation on the input byte pattern) out of an appropriately-sized byte view.

Is this key pattern of array::from_fn({let view = must_cast_ref(…); |i| construct(&view[i])}) a good practice, or am I going about it the wrong way?

I'd probably do this instead:

pub fn load_foobunch(arr: &[u8; std::mem::size_of::<[Foo; 42]>()]) -> [Foo; 42] {
    let mut iter = arr
        .chunks_exact(std::mem::size_of::<Foo>())
        .map(|c| crate::construct_one_foo(c.try_into().unwrap()));
    core::array::from_fn(|_| iter.next().unwrap())
}

Replacing must_cast_ref with chunks_exact seems to trade compile-time typo checking for run-time checks that silently ignore mistakes. Are there any benefits to doing that?

Usually the .try_into().unwrap() optimizes out. Not sure if .next().unwrap() does but yours also has view[i] so it's probably not much different. If you want something that doesn't panic you can map the whole thing.

fn load_foobunch(arr: &[u8; std::mem::size_of::<[Foo; 42]>()]) -> [Foo; 42] {
    bytemuck::must_cast_ref::<_, [_; 42]>(arr).map(|s| crate::construct_one_foo(&s))
}

This could be slower if it copies unnecessarily.

1 Like

I see, so of the 3 approaches discussed so far:

  • from_fn + must_cast_ref provides compile-time typo checking
  • chunks_exact + map does run-time checks, and silently ignores mistakes
  • must_cast + map provides compile-time typo checking, but might confuse the optimizer

Am I interpreting this correctly?

Yeah, that's just my guesses though. The only thing the second one doesn't check is that std::mem::size_of::<Foo>() is the same as what construct_one_foo takes, but this kind of thing would either be typo-free or fail every time, so it's not really a risk.

If you're just going for readability, any of them should work. If you want to know which is faster, you'll have to test them.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.