zerocopy
zerocopy copied to clipboard
Implement `Ref::{try_as_ref,try_into_ref,try_into_mut}`
trafficstars
Only Ref::try_as_mut remains missing, probably pending polonius landing in rustc.
Partially fixes #1865 Supersedes #1184
A restricted form of Ref::try_as_mut can be implemented now as:
impl<B, T> Ref<B, T>
where
B: ByteSlice,
T: KnownLayout + ?Sized,
{
#[must_use = "has no side effects"]
#[inline(always)]
pub fn try_as_mut(r: &mut Self) -> Result<&mut T, ValidityError<&mut Self, T>>
where
T: TryFromBytes + Immutable,
B: ByteSliceMut + CloneableByteSlice,
{
// Presumably unreachable, since we've guarded each constructor of `Ref`.
static_assert_dst_is_not_zst!(T);
// Due to a false-positive in Rust's current borrow checker, the same
// `r` can't be used for both validation *and* be returned upon
// validation failure. We use `r_tmp` for validation, and `r` as the
// value returned upon failure.
let mut r_tmp = r.clone();
// SAFETY: We don't call any methods on `t` other than those provided by
// `ByteSlice`.
let b = unsafe { r_tmp.as_byte_slice_mut() };
match Ptr::from_mut(b.deref_mut()).try_cast_into_no_leftover::<T, BecauseExclusive>(None) {
Ok(candidate) => match candidate.try_into_valid() {
Ok(valid) => {
// SAFETY: `valid` inherits the local lifetime of `r_tmp`,
// but its value is derived from `r_tmp`'s underlying bytes.
// By contract on `CloneableByteSlice`, `r_temp.deref()
// produces a byte slice whose address (and thus lifetime)
// is identicial to that produced by `r.deref()`. We can
// therefor soundly extend the lifetime of `valid` to that
// of `r`.
Ok(unsafe { valid.assume_lifetime() }.as_mut())
},
Err(e) => Err(e.with_src(r)),
},
Err(CastError::Validity(i)) => match i {},
Err(CastError::Alignment(_) | CastError::Size(_)) => {
// SAFETY: By invariant on `Ref::0`, the referenced byte slice
// is aligned to `T`'s alignment and its size corresponds to a
// valid size for `T`. Since properties are checked upon
// constructing `Ref`, these failures are unreachable.
unsafe { core::hint::unreachable_unchecked() }
}
}
}
}
...but we don't yet implement ClonableByteSlice for anything except &[u8], so the method is effectively untestable.
Codecov Report
:x: Patch coverage is 94.87179% with 6 lines in your changes missing coverage. Please review.
:white_check_mark: Project coverage is 87.72%. Comparing base (0bee231) to head (311a259).
:warning: Report is 76 commits behind head on v0.8.x.
| Files with missing lines | Patch % | Lines |
|---|---|---|
| src/ref.rs | 94.59% | 6 Missing :warning: |
Additional details and impacted files
@@ Coverage Diff @@
## v0.8.x #1930 +/- ##
==========================================
+ Coverage 87.59% 87.72% +0.13%
==========================================
Files 16 16
Lines 5988 6103 +115
==========================================
+ Hits 5245 5354 +109
- Misses 743 749 +6
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
:rocket: New features to boost your workflow:
- :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.