macro_rules! try_transmute_mut {
($e:expr) => { ... };
}Expand description
Conditionally transmutes a mutable reference of one type to a mutable reference of another type of the same size and compatible alignment.
This macro behaves like an invocation of this function:
ⓘ
fn try_transmute_mut<Src, Dst>(src: &mut Src) -> Result<&mut Dst, ValidityError<&mut Src, Dst>>
where
Src: FromBytes + IntoBytes + ?Sized,
Dst: TryFromBytes + IntoBytes + ?Sized,
align_of::<Src>() >= align_of::<Dst>(),
size_compatible::<Src, Dst>(),
{
...
}The types Src and Dst are inferred from the calling context; they cannot
be explicitly specified in the macro invocation.
§Size compatibility
try_transmute_mut! supports transmuting between Sized types, between
unsized (i.e., ?Sized) types, and from a Sized type to an unsized type.
It supports any transmutation that preserves the number of bytes of the
referent, even if doing so requires updating the metadata stored in an
unsized “fat” reference:
let src: &mut [[u8; 2]] = &mut [[0, 1], [2, 3]][..];
let dst: &mut [u8] = try_transmute_mut!(src).unwrap();
assert_eq!(dst.len(), 4);
assert_eq!(dst, [0, 1, 2, 3]);
let dst_size = size_of_val(dst);
assert_eq!(src.len(), 2);
assert_eq!(size_of_val(src), dst_size);§Examples
Transmuting between Sized types:
// 0u8 → bool = false
let src = &mut 0u8;
assert_eq!(try_transmute_mut!(src), Ok(&mut false));
// 1u8 → bool = true
let src = &mut 1u8;
assert_eq!(try_transmute_mut!(src), Ok(&mut true));
// 2u8 → bool = error
let src = &mut 2u8;
assert!(matches!(
try_transmute_mut!(src),
Result::<&mut bool, _>::Err(ValidityError { .. })
));Transmuting between unsized types:
#[derive(KnownLayout, FromBytes, IntoBytes, Immutable)]
#[repr(C)]
struct SliceDst<T, U> {
t: T,
u: [U],
}
type Src = SliceDst<u32, u16>;
type Dst = SliceDst<u16, bool>;
let mut bytes = [0, 1, 0, 1, 0, 1, 0, 1];
let src = Src::mut_from_bytes(&mut bytes).unwrap();
assert_eq!(src.t.as_bytes(), [0, 1, 0, 1]);
assert_eq!(src.u.len(), 2);
assert_eq!(src.u.as_bytes(), [0, 1, 0, 1]);
let dst: &Dst = try_transmute_mut!(src).unwrap();
assert_eq!(dst.t.as_bytes(), [0, 1]);
assert_eq!(dst.u, [false, true, false, true, false, true]);