pub const unsafe fn transmute_copy<Src: ?Sized, Dst>(src: &Src) -> DstExpand 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 behindsrcmust be readable - The first
size_of::<Dst>()bytes behindsrcmust be valid when interpreted as aDst.
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()),
);