Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Self: IntoBytes bound to TryFromBytes::try_mut* #2331

Merged
merged 1 commit into from
Feb 14, 2025
Merged
Show file tree
Hide file tree
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
50 changes: 46 additions & 4 deletions src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1186,6 +1186,24 @@ mod tests {
}
}

pub(super) trait TestTryFromMut<T: ?Sized> {
#[allow(clippy::needless_lifetimes)]
fn test_try_from_mut<'bytes>(
&self,
bytes: &'bytes mut [u8],
) -> Option<Option<&'bytes mut T>>;
}

impl<T: TryFromBytes + IntoBytes + KnownLayout + ?Sized> TestTryFromMut<T> for AutorefWrapper<T> {
#[allow(clippy::needless_lifetimes)]
fn test_try_from_mut<'bytes>(
&self,
bytes: &'bytes mut [u8],
) -> Option<Option<&'bytes mut T>> {
Some(T::try_mut_from_bytes(bytes).ok())
}
}

pub(super) trait TestTryReadFrom<T> {
fn test_try_read_from(&self, bytes: &[u8]) -> Option<Option<T>>;
}
Expand Down Expand Up @@ -1277,6 +1295,25 @@ mod tests {
None
}

#[allow(clippy::needless_lifetimes)]
fn test_try_from_mut<'bytes>(&mut self, _bytes: &'bytes mut [u8]) -> Option<Option<&'bytes mut $ty>> {
assert_on_allowlist!(
test_try_from_mut($ty):
Option<Box<UnsafeCell<NotZerocopy>>>,
Option<&'static UnsafeCell<NotZerocopy>>,
Option<&'static mut UnsafeCell<NotZerocopy>>,
Option<NonNull<UnsafeCell<NotZerocopy>>>,
Option<fn()>,
Option<FnManyArgs>,
Option<extern "C" fn()>,
Option<ECFnManyArgs>,
*const NotZerocopy,
*mut NotZerocopy
);

None
}

fn test_try_read_from(&mut self, _bytes: &[u8]) -> Option<Option<&$ty>> {
assert_on_allowlist!(
test_try_read_from($ty):
Expand Down Expand Up @@ -1385,8 +1422,10 @@ mod tests {
let bytes_mut = &mut vec.as_mut_slice()[offset..offset+size];
bytes_mut.copy_from_slice(bytes);

let res = <$ty as TryFromBytes>::try_mut_from_bytes(bytes_mut);
assert!(res.is_ok(), "{}::try_mut_from_bytes({:?}): got `Err`, expected `Ok`", stringify!($ty), val);
let res = ww.test_try_from_mut(bytes_mut);
if let Some(res) = res {
assert!(res.is_some(), "{}::try_mut_from_bytes({:?}): got `None`, expected `Some`", stringify!($ty), val);
}
}

let res = bytes.and_then(|bytes| ww.test_try_read_from(bytes));
Expand All @@ -1406,8 +1445,11 @@ mod tests {
assert!(res.is_none(), "{}::try_ref_from_bytes({:?}): got Some, expected None", stringify!($ty), c);
}

let res = <$ty as TryFromBytes>::try_mut_from_bytes(c);
assert!(res.is_err(), "{}::try_mut_from_bytes({:?}): got Ok, expected Err", stringify!($ty), c);
let res = w.test_try_from_mut(c);
if let Some(res) = res {
assert!(res.is_none(), "{}::try_mut_from_bytes({:?}): got Some, expected None", stringify!($ty), c);
}


let res = w.test_try_read_from(c);
if let Some(res) = res {
Expand Down
86 changes: 43 additions & 43 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1719,8 +1719,8 @@ pub unsafe trait TryFromBytes {
/// use zerocopy::*;
/// # use zerocopy_derive::*;
///
/// #[derive(TryFromBytes, KnownLayout)]
/// #[repr(C)]
/// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
/// #[repr(C, packed)]
/// struct ZSTy {
/// leading_sized: [u8; 2],
/// trailing_dst: [()],
Expand All @@ -1737,17 +1737,17 @@ pub unsafe trait TryFromBytes {
/// # use zerocopy_derive::*;
///
/// // The only valid value of this type is the byte `0xC0`
/// #[derive(TryFromBytes, KnownLayout)]
/// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
/// #[repr(u8)]
/// enum C0 { xC0 = 0xC0 }
///
/// // The only valid value of this type is the bytes `0xC0C0`.
/// #[derive(TryFromBytes, KnownLayout)]
/// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
/// #[repr(C)]
/// struct C0C0(C0, C0);
///
/// #[derive(TryFromBytes, KnownLayout)]
/// #[repr(C)]
/// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
/// #[repr(C, packed)]
/// struct Packet {
/// magic_number: C0C0,
/// mug_size: u8,
Expand Down Expand Up @@ -1775,7 +1775,7 @@ pub unsafe trait TryFromBytes {
#[inline]
fn try_mut_from_bytes(bytes: &mut [u8]) -> Result<&mut Self, TryCastError<&mut [u8], Self>>
where
Self: KnownLayout,
Self: KnownLayout + IntoBytes,
{
static_assert_dst_is_not_zst!(Self);
match Ptr::from_mut(bytes).try_cast_into_no_leftover::<Self, BecauseExclusive>(None) {
Expand Down Expand Up @@ -1827,8 +1827,8 @@ pub unsafe trait TryFromBytes {
/// use zerocopy::*;
/// # use zerocopy_derive::*;
///
/// #[derive(TryFromBytes, KnownLayout)]
/// #[repr(C)]
/// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
/// #[repr(C, packed)]
/// struct ZSTy {
/// leading_sized: [u8; 2],
/// trailing_dst: [()],
Expand All @@ -1845,17 +1845,17 @@ pub unsafe trait TryFromBytes {
/// # use zerocopy_derive::*;
///
/// // The only valid value of this type is the byte `0xC0`
/// #[derive(TryFromBytes, KnownLayout)]
/// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
/// #[repr(u8)]
/// enum C0 { xC0 = 0xC0 }
///
/// // The only valid value of this type is the bytes `0xC0C0`.
/// #[derive(TryFromBytes, KnownLayout)]
/// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
/// #[repr(C)]
/// struct C0C0(C0, C0);
///
/// #[derive(TryFromBytes, KnownLayout)]
/// #[repr(C)]
/// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
/// #[repr(C, packed)]
/// struct Packet {
/// magic_number: C0C0,
/// mug_size: u8,
Expand Down Expand Up @@ -1888,7 +1888,7 @@ pub unsafe trait TryFromBytes {
source: &mut [u8],
) -> Result<(&mut Self, &mut [u8]), TryCastError<&mut [u8], Self>>
where
Self: KnownLayout,
Self: KnownLayout + IntoBytes,
{
static_assert_dst_is_not_zst!(Self);
try_mut_from_prefix_suffix(source, CastType::Prefix, None)
Expand Down Expand Up @@ -1922,8 +1922,8 @@ pub unsafe trait TryFromBytes {
/// use zerocopy::*;
/// # use zerocopy_derive::*;
///
/// #[derive(TryFromBytes, KnownLayout)]
/// #[repr(C)]
/// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
/// #[repr(C, packed)]
/// struct ZSTy {
/// leading_sized: u16,
/// trailing_dst: [()],
Expand All @@ -1940,17 +1940,17 @@ pub unsafe trait TryFromBytes {
/// # use zerocopy_derive::*;
///
/// // The only valid value of this type is the byte `0xC0`
/// #[derive(TryFromBytes, KnownLayout)]
/// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
/// #[repr(u8)]
/// enum C0 { xC0 = 0xC0 }
///
/// // The only valid value of this type is the bytes `0xC0C0`.
/// #[derive(TryFromBytes, KnownLayout)]
/// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
/// #[repr(C)]
/// struct C0C0(C0, C0);
///
/// #[derive(TryFromBytes, KnownLayout)]
/// #[repr(C)]
/// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
/// #[repr(C, packed)]
/// struct Packet {
/// magic_number: C0C0,
/// mug_size: u8,
Expand Down Expand Up @@ -1983,7 +1983,7 @@ pub unsafe trait TryFromBytes {
source: &mut [u8],
) -> Result<(&mut [u8], &mut Self), TryCastError<&mut [u8], Self>>
where
Self: KnownLayout,
Self: KnownLayout + IntoBytes,
{
static_assert_dst_is_not_zst!(Self);
try_mut_from_prefix_suffix(source, CastType::Suffix, None).map(swap)
Expand Down Expand Up @@ -2292,17 +2292,17 @@ pub unsafe trait TryFromBytes {
/// # use zerocopy_derive::*;
///
/// // The only valid value of this type is the byte `0xC0`
/// #[derive(TryFromBytes, KnownLayout)]
/// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
/// #[repr(u8)]
/// enum C0 { xC0 = 0xC0 }
///
/// // The only valid value of this type is the bytes `0xC0C0`.
/// #[derive(TryFromBytes, KnownLayout)]
/// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
/// #[repr(C)]
/// struct C0C0(C0, C0);
///
/// #[derive(TryFromBytes, KnownLayout)]
/// #[repr(C)]
/// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
/// #[repr(C, packed)]
/// struct Packet {
/// magic_number: C0C0,
/// mug_size: u8,
Expand Down Expand Up @@ -2336,8 +2336,8 @@ pub unsafe trait TryFromBytes {
/// use zerocopy::*;
/// # use zerocopy_derive::*;
///
/// #[derive(TryFromBytes, KnownLayout)]
/// #[repr(C)]
/// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
/// #[repr(C, packed)]
/// struct ZSTy {
/// leading_sized: NonZeroU16,
/// trailing_dst: [()],
Expand All @@ -2357,7 +2357,7 @@ pub unsafe trait TryFromBytes {
count: usize,
) -> Result<&mut Self, TryCastError<&mut [u8], Self>>
where
Self: KnownLayout<PointerMetadata = usize>,
Self: KnownLayout<PointerMetadata = usize> + IntoBytes,
{
match Ptr::from_mut(source).try_cast_into_no_leftover::<Self, BecauseExclusive>(Some(count))
{
Expand Down Expand Up @@ -2403,17 +2403,17 @@ pub unsafe trait TryFromBytes {
/// # use zerocopy_derive::*;
///
/// // The only valid value of this type is the byte `0xC0`
/// #[derive(TryFromBytes, KnownLayout)]
/// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
/// #[repr(u8)]
/// enum C0 { xC0 = 0xC0 }
///
/// // The only valid value of this type is the bytes `0xC0C0`.
/// #[derive(TryFromBytes, KnownLayout)]
/// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
/// #[repr(C)]
/// struct C0C0(C0, C0);
///
/// #[derive(TryFromBytes, KnownLayout)]
/// #[repr(C)]
/// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
/// #[repr(C, packed)]
/// struct Packet {
/// magic_number: C0C0,
/// mug_size: u8,
Expand Down Expand Up @@ -2449,8 +2449,8 @@ pub unsafe trait TryFromBytes {
/// use zerocopy::*;
/// # use zerocopy_derive::*;
///
/// #[derive(TryFromBytes, KnownLayout)]
/// #[repr(C)]
/// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
/// #[repr(C, packed)]
/// struct ZSTy {
/// leading_sized: NonZeroU16,
/// trailing_dst: [()],
Expand All @@ -2470,7 +2470,7 @@ pub unsafe trait TryFromBytes {
count: usize,
) -> Result<(&mut Self, &mut [u8]), TryCastError<&mut [u8], Self>>
where
Self: KnownLayout<PointerMetadata = usize>,
Self: KnownLayout<PointerMetadata = usize> + IntoBytes,
{
try_mut_from_prefix_suffix(source, CastType::Prefix, Some(count))
}
Expand Down Expand Up @@ -2498,17 +2498,17 @@ pub unsafe trait TryFromBytes {
/// # use zerocopy_derive::*;
///
/// // The only valid value of this type is the byte `0xC0`
/// #[derive(TryFromBytes, KnownLayout)]
/// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
/// #[repr(u8)]
/// enum C0 { xC0 = 0xC0 }
///
/// // The only valid value of this type is the bytes `0xC0C0`.
/// #[derive(TryFromBytes, KnownLayout)]
/// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
/// #[repr(C)]
/// struct C0C0(C0, C0);
///
/// #[derive(TryFromBytes, KnownLayout)]
/// #[repr(C)]
/// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
/// #[repr(C, packed)]
/// struct Packet {
/// magic_number: C0C0,
/// mug_size: u8,
Expand Down Expand Up @@ -2544,8 +2544,8 @@ pub unsafe trait TryFromBytes {
/// use zerocopy::*;
/// # use zerocopy_derive::*;
///
/// #[derive(TryFromBytes, KnownLayout)]
/// #[repr(C)]
/// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
/// #[repr(C, packed)]
/// struct ZSTy {
/// leading_sized: NonZeroU16,
/// trailing_dst: [()],
Expand All @@ -2565,7 +2565,7 @@ pub unsafe trait TryFromBytes {
count: usize,
) -> Result<(&mut [u8], &mut Self), TryCastError<&mut [u8], Self>>
where
Self: KnownLayout<PointerMetadata = usize>,
Self: KnownLayout<PointerMetadata = usize> + IntoBytes,
{
try_mut_from_prefix_suffix(source, CastType::Suffix, Some(count)).map(swap)
}
Expand Down Expand Up @@ -2777,7 +2777,7 @@ fn try_ref_from_prefix_suffix<T: TryFromBytes + KnownLayout + Immutable + ?Sized
}

#[inline(always)]
fn try_mut_from_prefix_suffix<T: TryFromBytes + KnownLayout + ?Sized>(
fn try_mut_from_prefix_suffix<T: IntoBytes + TryFromBytes + KnownLayout + ?Sized>(
candidate: &mut [u8],
cast_type: CastType,
meta: Option<T::PointerMetadata>,
Expand Down
12 changes: 6 additions & 6 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,8 @@ macro_rules! transmute_ref {
/// const fn transmute_mut<'src, 'dst, Src, Dst>(src: &'src mut Src) -> &'dst mut Dst
/// where
/// 'src: 'dst,
/// Src: FromBytes + IntoBytes + Immutable,
/// Dst: FromBytes + IntoBytes + Immutable,
/// Src: FromBytes + IntoBytes,
/// Dst: FromBytes + IntoBytes,
/// size_of::<Src>() == size_of::<Dst>(),
/// align_of::<Src>() >= align_of::<Dst>(),
/// {
Expand Down Expand Up @@ -325,9 +325,9 @@ macro_rules! transmute_mut {
#[allow(unused, clippy::diverging_sub_expression)]
if false {
// This branch, though never taken, ensures that the type of `e` is
// `&mut T` where `T: 't + Sized + FromBytes + IntoBytes + Immutable`
// and that the type of this macro expression is `&mut U` where `U:
// 'u + Sized + FromBytes + IntoBytes + Immutable`.
// `&mut T` where `T: 't + Sized + FromBytes + IntoBytes` and that
// the type of this macro expression is `&mut U` where `U: 'u +
// Sized + FromBytes + IntoBytes`.

// We use immutable references here rather than mutable so that, if
// this macro is used in a const context (in which, as of this
Expand Down Expand Up @@ -578,7 +578,7 @@ macro_rules! try_transmute_ref {
/// fn try_transmute_mut<Src, Dst>(src: &mut Src) -> Result<&mut Dst, ValidityError<&mut Src, Dst>>
/// where
/// Src: FromBytes + IntoBytes,
/// Dst: TryFromBytes,
/// Dst: TryFromBytes + IntoBytes,
/// size_of::<Src>() == size_of::<Dst>(),
/// align_of::<Src>() >= align_of::<Dst>(),
/// {
Expand Down
2 changes: 1 addition & 1 deletion src/util/macro_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,7 @@ where
pub fn try_transmute_mut<Src, Dst>(src: &mut Src) -> Result<&mut Dst, ValidityError<&mut Src, Dst>>
where
Src: FromBytes + IntoBytes,
Dst: TryFromBytes,
Dst: TryFromBytes + IntoBytes,
{
match try_cast_or_pme::<Src, Dst, _, BecauseExclusive>(Ptr::from_mut(src)) {
Ok(ptr) => {
Expand Down
Loading