Skip to main content

transmute_prefix

Function transmute_prefix 

Source
pub const unsafe fn transmute_prefix<Src, Dst>(src: Src) -> Dst
🔬This is a nightly-only experimental API. (transmute_prefix #155079)
Expand description

Like transmute, but only initializes the “common prefix” of the first min(size_of::<Src>(), size_of::<Dst>()) bytes of the destination from the corresponding bytes of the source.

This is equivalent to a “union cast” through a union with #[repr(C)].

That means some size mismatches are not UB, like [T; 2] to [T; 1]. Increasing size is usually UB from being insufficiently initialized – like u8 to u32 – but isn’t always. For example, going from u8 to #[repr(C, align(4))] AlignedU8(u8); is sound.

Prefer normal transmute where possible, for the extra checking, since both do exactly the same thing at runtime, if they both compile.

§Safety

If size_of::<Src>() >= size_of::<Dst>(), the first size_of::<Dst>() bytes of src must be be valid when interpreted as a Dst. (In this case, the preconditions are the same as for transmute_copy(&ManuallyDrop::new(src)).)

If size_of::<Src>() <= size_of::<Dst>(), the bytes of src padded with uninitialized bytes afterwards up to a total size of size_of::<Dst>() must be valid when interpreted as a Dst.

In both cases, any safety preconditions of the Dst type must also be upheld.

§Examples

#![feature(transmute_prefix)]
use std::mem::transmute_prefix;

assert_eq!(unsafe { transmute_prefix::<[i32; 4], [i32; 2]>([1, 2, 3, 4]) }, [1, 2]);

let expected = if cfg!(target_endian = "little") { 0x34 } else { 0x12 };
assert_eq!(unsafe { transmute_prefix::<u16, u8>(0x1234) }, expected);

// Would be UB because the destination is incompletely initialized.
// transmute_prefix::<u8, u16>(123)

// OK because the destination is allowed to be partially initialized.
let _: std::mem::MaybeUninit<u16> = unsafe { transmute_prefix(123_u8) };