Search code examples
multidimensional-arrayrustunsafe

What's the best way to convert a [[T; 4]; 3] into a [T; 12]?


As I understand it, a [[T; 4]; 3] and a [T; 12] have the same layout in memory. What is the best way to convert a value between these types? Can I convert a reference to one into a reference to the other? Can I avoid copying all the elements? Do I need unsafe?


Solution

  • Yes, you can convert a reference to a [[T; 4]; 3] into a reference to a [T; 12], but only with unsafe code, using mem::transmute. It's best to wrap this in a function so that the resulting reference is assigned the proper lifetime, as otherwise transmute would make it possible to obtain a reference with a larger lifetime than the reference should have.

    fn convert<'a>(a: &'a [[u8; 4]; 3]) -> &'a [u8; 12] {
        unsafe { std::mem::transmute(a) }
    }
    

    This can be shortened thanks to the lifetime elision rules:

    fn convert(a: &[[u8; 4]; 3]) -> &[u8; 12] {
        unsafe { std::mem::transmute(a) }
    }
    

    Though when dealing with unsafe code, I'd understand if you preferred the more explicit version!