Skip to main content

transmute_copy

Function transmute_copy 

1.6.0 (const: 1.74.0) · Source
pub const unsafe fn transmute_copy<Src: ?Sized, Dst>(src: &Src) -> Dst
Expand description

Interprets src as having type &Dst, and then reads src without moving the contained value.

This function will unsafely assume the pointer src is valid for size_of::<Dst> bytes by transmuting &Src to &Dst and then reading the &Dst (except that this is done in a way that is correct even when &Dst has stricter alignment requirements than &Src). It will also unsafely create a copy of the contained value instead of moving out of src.

It is not a compile-time error if Src and Dst have different sizes, but it is highly encouraged to only invoke this function where Src and Dst have the same size. This function triggers undefined behavior if Dst is larger than Src.

If you have a raw pointer instead of a reference, you might be looking for src.cast::<Dst>().read_unaligned() instead.

§Safety

  • Requires size_of_val::<Src>(src) >= size_of::<Dst>()
  • The first size_of::<Dst>() bytes behind src must be readable
  • The first size_of::<Dst>() bytes behind src must be valid when interpreted as a Dst.

On top of that, remember that most types have additional invariants beyond merely being considered initialized at the type level. For example, a 1-initialized Vec<T> is considered initialized (under the current implementation; this does not constitute a stable guarantee) because the only requirement the compiler knows about it is that the data pointer must be non-null. Creating such a Vec<T> does not cause immediate undefined behavior, but will cause undefined behavior with most safe operations (including dropping it).

§Examples

use std::mem;

#[repr(packed)]
struct Foo {
    bar: u8,
}

let foo_array = [10u8];

unsafe {
    // Copy the data from 'foo_array' and treat it as a 'Foo'
    let mut foo_struct: Foo = mem::transmute_copy(&foo_array);
    assert_eq!(foo_struct.bar, 10);

    // Modify the copied data
    foo_struct.bar = 20;
    assert_eq!(foo_struct.bar, 20);
}

// The contents of 'foo_array' should not have changed
assert_eq!(foo_array, [10]);

let bytes: &[u8] = &[1, 2, 3, 4, 5, 6, 7];
assert_eq!(
    unsafe { mem::transmute_copy::<[u8], u32>(bytes) },
    u32::from_ne_bytes(*bytes.first_chunk().unwrap()),
);