Is this transmute + read_exact safe?

fn read_buffer_i32<R: std::io::Read>(reader: &mut R, n: usize) -> Result<Vec<i32>> {
    // todo: assert that machine endianess equals what the reader claims to contain

    let bytes = n * 4;
    let mut buffer = vec![0i32; n];
    unsafe {
        // transmute i32 to bytes under native endieness
        let slice = std::slice::from_raw_parts_mut(buffer.as_mut_ptr() as *mut u8, bytes);
        reader.read_exact(slice)?;
    }
    Ok(buffer)
}

if not, is there a way to perform this operation without having to allocate an extra buffer of u8 and perform the conversion to the final Vec<i32>.

Yes, this is sound. (There are also some crates like safe-transmute and dataview that provide safe methods for converting from &mut [i32] to &mut [u8], if you prefer to depend on someone else's unsafe code.)

2 Likes

You can avoid allocating an intermediate u8 buffer by using a [u8; 4] array on the stack, and i32::from_ne_bytes() avoids the implicit transmute you get from type punning slice.

As long as R does some sort of buffering under the hood, I would expect something like this to have identical performance while also not requiring unsafe code.

pub fn read_buffer_i32_safe<R: Read>(reader: &mut R, n: usize) -> Result<Vec<i32>> {
    let mut numbers = Vec::with_capacity(n);
    
    for _ in 0..n {
        let mut buffer = [0; std::mem::size_of::<i32>()];
        reader.read_exact(&mut buffer)?;
        numbers.push(i32::from_ne_bytes(buffer));
    }
    
    Ok(numbers)
}
1 Like

Doesn't this assume that reader.read_exact(&mut [0; 4])?; times n has the same performance than reader.read_exact(&mut [0; 4*n])?;?

If reader is e.g. a file, I would expect a major difference if n is beyond any buffering applied to it.

Yep. That's exactly what I meant when I said

As long as R does some sort of buffering under the hood, I would expect something like this to have identical performance

it's pretty typical to wrap a File in a std::io::BufReader though, so I wouldn't say that's a deal breaker.

1 Like

I believe the most popular crate for this is bytemuck

1 Like

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.