Array reference from raw parts missing?

I am migrating an application to Rust and have currently a pretty big interface between Rust an C code.

A few times now I have needed to get an array reference from a pointer and a compile time fixed size. Something like this:

unsafe fn array_from_raw_parts_mut<'a, const N: usize, T>(data: *mut T) -> &'a mut [T; N] {
    &mut *(data as *mut [T; N])

I am wondering: should this part of the std lib, or has this intentionally been left out?

"parts" would imply more than one part, no?

Oh well :smile: I was pretty focused on slice::from_raw_parts() when I wrote this. array_ref_from_ptr or ptr::as_array_ref might be better names.

But naming aside: is this functionality something that would make sense as part of the standard library?

Some of those "from_raw" APIs exists because the types created don't have a stable layout, or because using literal "transmute" might seem too harsh. The available ways to create *mut [T; N] from *mut T (e. g. by casting), or &mut U from *mut U (e. g. by dereferencing) are less bad IMO, and there's even alternatives, e.g. the cast method to avoid coercion or the as_mut method for doing essentially &mut *x in a pointer, but with an additional null check.

(So as a consequence, you can re-write your implementation as &mut *data.cast::<[T; N]>() in case you'd prefer that. Or if you're brave and can rely on type inference, even &mut *data.cast().)

So I guess the main question here is whether or not converting *mut T to &mut [T; N] in a single step, rather than in two steps is an important enough operation to give it its own method/function. Perhaps that was already clear to you, I just wanted to point it out :slight_smile: So we'd need to consider pros and cons of having a dedicated single-step conversion vs. doing it in two steps.

regarding your use-case, I haven't double-checked it, but I would assume [T; N] is FFI safe, so if you have a known fixed size, say length 42, array (pointer) then you could perhaps directly work with *mut [T; 42] in the first place instead ever using a *mut T?

1 Like

Oh well... Thank you a lot :blush:

Taking *mut [u8; 16] seems to be working flawlessly, in hindsight this is obvious.

One thing I noticed: I can also use &mut [u8; 16] in an ffi function (either calling C code or being called by C code) and Rust will not complain. Is this valid or should I rather use pointers?

Yes, that's valid, too. Of course you need to make sure to uphold the safety guarantees for &mut e. g. when calling from C for a &mut argument, or calling into C for a &mut return type, but that's the same if you wrap the function.

1 Like

Thank you :heart:

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.