Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 25 additions & 23 deletions src/pointer/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1162,30 +1162,18 @@ mod _casts {
U: 'a + ?Sized + KnownLayout + Read<I::Aliasing, R>,
[u8]: Read<I::Aliasing, R>,
{
// FIXME(#67): Remove this allow. See NonNullExt for more details.
#[allow(unstable_name_collisions)]
match self.try_cast_into(CastType::Prefix, meta) {
Ok((slf, remainder)) => {
if remainder.len() == 0 {
Ok(slf)
} else {
// Undo the cast so we can return the original bytes.
let slf = slf.as_bytes();
// Restore the initial alignment invariant of `self`.
//
// SAFETY: The referent type of `slf` is now equal to
// that of `self`, but the alignment invariants
// nominally differ. Since `slf` and `self` refer to the
// same memory and no actions have been taken that would
// violate the original invariants on `self`, it is
// sound to apply the alignment invariant of `self` onto
// `slf`.
let slf = unsafe { slf.assume_alignment::<I::Alignment>() };
let slf = slf.unify_invariants();
Err(CastError::Size(SizeError::<_, U>::new(slf)))
// SAFETY: The provided closure returns the only copy of `slf`.
unsafe {
self.try_with_unchecked(|slf| match slf.try_cast_into(CastType::Prefix, meta) {
Ok((slf, remainder)) => {
if remainder.len() == 0 {
Ok(slf)
} else {
Err(CastError::Size(SizeError::<_, U>::new(())))
}
}
}
Err(err) => Err(err),
Err(err) => Err(err.map_src(|_slf| ())),
})
}
}
}
Expand Down Expand Up @@ -1523,4 +1511,18 @@ mod tests {
// succeed.
test!(Dst, 8, usize::MAX - 8 + 1, None);
}

#[test]
fn test_try_cast_into_no_leftover_restores_original_slice() {
let bytes = [0u8; 4];
let ptr = Ptr::from_ref(&bytes[..]);
let res = ptr.try_cast_into_no_leftover::<[u8; 2], BecauseImmutable>(None);
match res {
Ok(_) => panic!("should have failed due to leftover bytes"),
Err(CastError::Size(e)) => {
assert_eq!(e.into_src().len(), 4, "Should return original slice length");
}
Err(e) => panic!("wrong error type: {:?}", e),
}
}
}
Loading