-
Notifications
You must be signed in to change notification settings - Fork 142
Closed
Description
We should implement try_transmute!, analogous to transmute!, that performs compile-time size and alignment checks, but also a run-time validity check.
Considerations
Due to the run-time validity check, this macro will not be usable in const contexts for the foreseeable future. (But we could perhaps work around this by also providing const fn is_bit_valid inherent methods in our derive; see #115.)
The implementation should avoid performing dynamic size or alignment checks.
Steps
Once #999 is merged, we can define a typed alternative to is_bit_valid on TryFromBytes:
#[doc(hidden)]
#[inline]
fn is_src_valid<Src>(src: &mut Src) -> bool
where
Src: IntoBytes,
Self: Sized,
{
let c_ptr = crate::Ptr::from_mut(src);
if mem::size_of::<Src>() > mem::size_of::<Self>() {
return false;
}
// SAFETY:
// - `size_of::<Src>()` <= `size_of::<Self>()`
// - `c_ptr` is exclusively aliased, so we do not need to reason about
// `UnsafeCell`
let c_ptr = unsafe { c_ptr.cast_unsized(|p| p as *mut Self) };
// SAFETY: `c_ptr` is derived from `src` which is `IntoBytes`. By
// invariant on `IntoByte`s, `c_ptr`'s referent consists entirely of
// initialized bytes.
let c_ptr = unsafe { c_ptr.assume_validity::<crate::invariant::Initialized>() };
Self::is_bit_valid(c_ptr)
}The dynamic components of try_transmute! can then be factored into a helper function:
/// A helper for `try_transmute!`.
#[inline(always)]
pub fn try_transmute<Src, Dst>(mut src: Src) -> Option<Dst>
where
Src: IntoBytes,
Dst: TryFromBytes,
{
if !Dst::is_src_valid(&mut src) {
return None;
}
let src = ManuallyDrop::new(src);
// SAFETY:
// - `src` is a bit-valid instance of `Dst`
// - `src` is `ManuallyDrop`
Some(unsafe { core::mem::transmute_copy(&*src) })
}Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels