pub const unsafe fn transmute_prefix<Src, Dst>(src: Src) -> Dsttransmute_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) };