Skip to content

Commit 84719d9

Browse files
authored
Refactor try_read_from_xxx (#1810)
1 parent 8e742d8 commit 84719d9

File tree

1 file changed

+44
-78
lines changed

1 file changed

+44
-78
lines changed

src/lib.rs

Lines changed: 44 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -2539,37 +2539,15 @@ pub unsafe trait TryFromBytes {
25392539
where
25402540
Self: Sized,
25412541
{
2542-
// Note that we have to call `is_bit_valid` on an exclusive-aliased
2543-
// pointer since we don't require `Self: Immutable`. That's why we do `let
2544-
// mut` and `Ptr::from_mut` here. See the doc comment on `is_bit_valid`
2545-
// and the implementation of `TryFromBytes` for `UnsafeCell` for more
2546-
// details.
2547-
let mut candidate = match MaybeUninit::<Self>::read_from_bytes(source) {
2542+
let candidate = match MaybeUninit::<Self>::read_from_bytes(source) {
25482543
Ok(candidate) => candidate,
25492544
Err(e) => {
25502545
return Err(TryReadError::Size(e.with_dst()));
25512546
}
25522547
};
2553-
let c_ptr = Ptr::from_mut(&mut candidate);
2554-
let c_ptr = c_ptr.transparent_wrapper_into_inner();
2555-
// SAFETY: `c_ptr` has no uninitialized sub-ranges because it derived
2556-
// from `candidate`, which in turn derives from `source: &[u8]`.
2557-
let c_ptr = unsafe { c_ptr.assume_validity::<invariant::Initialized>() };
2558-
2559-
// This call may panic. If that happens, it doesn't cause any soundness
2560-
// issues, as we have not generated any invalid state which we need to
2561-
// fix before returning.
2562-
//
2563-
// Note that one panic or post-monomorphization error condition is
2564-
// calling `try_into_valid` (and thus `is_bit_valid`) with a shared
2565-
// pointer when `Self: !Immutable`. Since `Self: Immutable`, this panic
2566-
// condition will not happen.
2567-
if !Self::is_bit_valid(c_ptr.forget_aligned()) {
2568-
return Err(ValidityError::new(source).into());
2569-
}
2570-
2571-
// SAFETY: We just validated that `candidate` contains a valid `Self`.
2572-
Ok(unsafe { candidate.assume_init() })
2548+
// SAFETY: `candidate` was copied from from `source: &[u8]`, so all of
2549+
// its bytes are initialized.
2550+
unsafe { try_read_from(source, candidate) }
25732551
}
25742552

25752553
/// Attempts to read a `Self` from the prefix of the given `source`.
@@ -2622,37 +2600,15 @@ pub unsafe trait TryFromBytes {
26222600
where
26232601
Self: Sized,
26242602
{
2625-
// Note that we have to call `is_bit_valid` on an exclusive-aliased
2626-
// pointer since we don't require `Self: Immutable`. That's why we do `let
2627-
// mut` and `Ptr::from_mut` here. See the doc comment on `is_bit_valid`
2628-
// and the implementation of `TryFromBytes` for `UnsafeCell` for more
2629-
// details.
2630-
let (mut candidate, suffix) = match MaybeUninit::<Self>::read_from_prefix(source) {
2603+
let (candidate, suffix) = match MaybeUninit::<Self>::read_from_prefix(source) {
26312604
Ok(candidate) => candidate,
26322605
Err(e) => {
26332606
return Err(TryReadError::Size(e.with_dst()));
26342607
}
26352608
};
2636-
let c_ptr = Ptr::from_mut(&mut candidate);
2637-
let c_ptr = c_ptr.transparent_wrapper_into_inner();
2638-
// SAFETY: `c_ptr` has no uninitialized sub-ranges because it derived
2639-
// from `candidate`, which in turn derives from `source: &[u8]`.
2640-
let c_ptr = unsafe { c_ptr.assume_validity::<invariant::Initialized>() };
2641-
2642-
// This call may panic. If that happens, it doesn't cause any soundness
2643-
// issues, as we have not generated any invalid state which we need to
2644-
// fix before returning.
2645-
//
2646-
// Note that one panic or post-monomorphization error condition is
2647-
// calling `try_into_valid` (and thus `is_bit_valid`) with a shared
2648-
// pointer when `Self: !Immutable`. Since `Self: Immutable`, this panic
2649-
// condition will not happen.
2650-
if !Self::is_bit_valid(c_ptr.forget_aligned()) {
2651-
return Err(ValidityError::new(source).into());
2652-
}
2653-
2654-
// SAFETY: We just validated that `candidate` contains a valid `Self`.
2655-
Ok((unsafe { candidate.assume_init() }, suffix))
2609+
// SAFETY: `candidate` was copied from from `source: &[u8]`, so all of
2610+
// its bytes are initialized.
2611+
unsafe { try_read_from(source, candidate).map(|slf| (slf, suffix)) }
26562612
}
26572613

26582614
/// Attempts to read a `Self` from the suffix of the given `source`.
@@ -2706,37 +2662,15 @@ pub unsafe trait TryFromBytes {
27062662
where
27072663
Self: Sized,
27082664
{
2709-
// Note that we have to call `is_bit_valid` on an exclusive-aliased
2710-
// pointer since we don't require `Self: Immutable`. That's why we do `let
2711-
// mut` and `Ptr::from_mut` here. See the doc comment on `is_bit_valid`
2712-
// and the implementation of `TryFromBytes` for `UnsafeCell` for more
2713-
// details.
2714-
let (prefix, mut candidate) = match MaybeUninit::<Self>::read_from_suffix(source) {
2665+
let (prefix, candidate) = match MaybeUninit::<Self>::read_from_suffix(source) {
27152666
Ok(candidate) => candidate,
27162667
Err(e) => {
27172668
return Err(TryReadError::Size(e.with_dst()));
27182669
}
27192670
};
2720-
let c_ptr = Ptr::from_mut(&mut candidate);
2721-
let c_ptr = c_ptr.transparent_wrapper_into_inner();
2722-
// SAFETY: `c_ptr` has no uninitialized sub-ranges because it derived
2723-
// from `candidate`, which in turn derives from `source: &[u8]`.
2724-
let c_ptr = unsafe { c_ptr.assume_validity::<invariant::Initialized>() };
2725-
2726-
// This call may panic. If that happens, it doesn't cause any soundness
2727-
// issues, as we have not generated any invalid state which we need to
2728-
// fix before returning.
2729-
//
2730-
// Note that one panic or post-monomorphization error condition is
2731-
// calling `try_into_valid` (and thus `is_bit_valid`) with a shared
2732-
// pointer when `Self: !Immutable`. Since `Self: Immutable`, this panic
2733-
// condition will not happen.
2734-
if !Self::is_bit_valid(c_ptr.forget_aligned()) {
2735-
return Err(ValidityError::new(source).into());
2736-
}
2737-
2738-
// SAFETY: We just validated that `candidate` contains a valid `Self`.
2739-
Ok((prefix, unsafe { candidate.assume_init() }))
2671+
// SAFETY: `candidate` was copied from from `source: &[u8]`, so all of
2672+
// its bytes are initialized.
2673+
unsafe { try_read_from(source, candidate).map(|slf| (prefix, slf)) }
27402674
}
27412675
}
27422676

@@ -2795,6 +2729,38 @@ fn swap<T, U>((t, u): (T, U)) -> (U, T) {
27952729
(u, t)
27962730
}
27972731

2732+
/// # Safety
2733+
///
2734+
/// All bytes of `candidate` must be initialized.
2735+
#[inline(always)]
2736+
unsafe fn try_read_from<S, T: TryFromBytes>(
2737+
source: S,
2738+
mut candidate: MaybeUninit<T>,
2739+
) -> Result<T, TryReadError<S, T>> {
2740+
// We use `from_mut` despite not mutating via `c_ptr` so that we don't need
2741+
// to add a `T: Immutable` bound.
2742+
let c_ptr = Ptr::from_mut(&mut candidate);
2743+
let c_ptr = c_ptr.transparent_wrapper_into_inner();
2744+
// SAFETY: `c_ptr` has no uninitialized sub-ranges because it derived from
2745+
// `candidate`, which the caller promises is entirely initialized.
2746+
let c_ptr = unsafe { c_ptr.assume_validity::<invariant::Initialized>() };
2747+
2748+
// This call may panic. If that happens, it doesn't cause any soundness
2749+
// issues, as we have not generated any invalid state which we need to
2750+
// fix before returning.
2751+
//
2752+
// Note that one panic or post-monomorphization error condition is
2753+
// calling `try_into_valid` (and thus `is_bit_valid`) with a shared
2754+
// pointer when `Self: !Immutable`. Since `Self: Immutable`, this panic
2755+
// condition will not happen.
2756+
if !T::is_bit_valid(c_ptr.forget_aligned()) {
2757+
return Err(ValidityError::new(source).into());
2758+
}
2759+
2760+
// SAFETY: We just validated that `candidate` contains a valid `T`.
2761+
Ok(unsafe { candidate.assume_init() })
2762+
}
2763+
27982764
/// Types for which a sequence of bytes all set to zero represents a valid
27992765
/// instance of the type.
28002766
///

0 commit comments

Comments
 (0)