Skip to content

Commit 07d6369

Browse files
committed
Implement FromBytes::{mut,ref}_from_with_trailing_elements
Makes progress on #29
1 parent f8057e9 commit 07d6369

File tree

1 file changed

+158
-9
lines changed

1 file changed

+158
-9
lines changed

src/lib.rs

+158-9
Original file line numberDiff line numberDiff line change
@@ -1380,7 +1380,7 @@ pub unsafe trait TryFromBytes {
13801380
/// #[derive(TryFromBytes, Immutable, KnownLayout)]
13811381
/// #[repr(C)]
13821382
/// struct ZSTy {
1383-
/// leading_sized: u16,
1383+
/// leading_sized: [u8; 2],
13841384
/// trailing_dst: [()],
13851385
/// }
13861386
///
@@ -1476,7 +1476,7 @@ pub unsafe trait TryFromBytes {
14761476
/// #[derive(TryFromBytes, Immutable, KnownLayout)]
14771477
/// #[repr(C)]
14781478
/// struct ZSTy {
1479-
/// leading_sized: u16,
1479+
/// leading_sized: [u8; 2],
14801480
/// trailing_dst: [()],
14811481
/// }
14821482
///
@@ -2499,7 +2499,7 @@ pub unsafe trait FromBytes: FromZeros {
24992499
/// #[derive(FromBytes, Immutable, IntoBytes, KnownLayout)]
25002500
/// #[repr(C, packed)]
25012501
/// struct ZSTy {
2502-
/// leading_sized: u16,
2502+
/// leading_sized: [u8; 2],
25032503
/// trailing_dst: [()],
25042504
/// }
25052505
///
@@ -2573,7 +2573,7 @@ pub unsafe trait FromBytes: FromZeros {
25732573
/// #[derive(FromBytes, Immutable, IntoBytes, KnownLayout)]
25742574
/// #[repr(C, packed)]
25752575
/// struct ZSTy {
2576-
/// leading_sized: u16,
2576+
/// leading_sized: [u8; 2],
25772577
/// trailing_dst: [()],
25782578
/// }
25792579
///
@@ -2647,7 +2647,7 @@ pub unsafe trait FromBytes: FromZeros {
26472647
/// #[derive(FromBytes, Immutable, IntoBytes, KnownLayout)]
26482648
/// #[repr(C, packed)]
26492649
/// struct ZSTy {
2650-
/// leading_sized: u16,
2650+
/// leading_sized: [u8; 2],
26512651
/// trailing_dst: [()],
26522652
/// }
26532653
///
@@ -2692,6 +2692,79 @@ pub unsafe trait FromBytes: FromZeros {
26922692
mut_from_prefix_suffix(bytes, None, CastType::Suffix).map(swap)
26932693
}
26942694

2695+
/// Interprets the given `bytes` as a `&Self` with a DST length equal to
2696+
/// `count`.
2697+
///
2698+
/// This method verifies that `bytes.len() == size_of::<T>() * count` and
2699+
/// that `bytes` is aligned to `align_of::<T>()`. It also ensures that
2700+
/// `sizeof::<T>() * count` does not overflow a `usize`. If any of the
2701+
/// length, alignment, or overflow checks fail, it returns `Err`.
2702+
///
2703+
/// # Examples
2704+
///
2705+
/// ```
2706+
/// use zerocopy::FromBytes;
2707+
/// # use zerocopy_derive::*;
2708+
///
2709+
/// # #[derive(Debug, PartialEq, Eq)]
2710+
/// #[derive(FromBytes, Immutable)]
2711+
/// #[repr(C)]
2712+
/// struct Pixel {
2713+
/// r: u8,
2714+
/// g: u8,
2715+
/// b: u8,
2716+
/// a: u8,
2717+
/// }
2718+
///
2719+
/// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7][..];
2720+
///
2721+
/// let pixels = <[Pixel]>::ref_from_with_trailing_elements(bytes, 2).unwrap();
2722+
///
2723+
/// assert_eq!(pixels, &[
2724+
/// Pixel { r: 0, g: 1, b: 2, a: 3 },
2725+
/// Pixel { r: 4, g: 5, b: 6, a: 7 },
2726+
/// ]);
2727+
///
2728+
/// ```
2729+
///
2730+
/// Since an explicit `count` is provided, this method supports types with
2731+
/// zero-sided trailing slice elements. Methods such as [`ref_from`]
2732+
/// which do not take an explicit count do not support such types.
2733+
///
2734+
/// ```
2735+
/// use zerocopy::*;
2736+
/// # use zerocopy_derive::*;
2737+
///
2738+
/// #[derive(FromBytes, Immutable, KnownLayout)]
2739+
/// #[repr(C)]
2740+
/// struct ZSTy {
2741+
/// leading_sized: [u8; 2],
2742+
/// trailing_dst: [()],
2743+
/// }
2744+
///
2745+
/// let src = &[85, 85][..];
2746+
/// let zsty = ZSTy::ref_from_with_trailing_elements(src, 42).unwrap();
2747+
/// assert_eq!(zsty.trailing_dst.len(), 42);
2748+
/// ```
2749+
///
2750+
/// [`ref_from`]: FromBytes::ref_from
2751+
#[must_use = "has no side effects"]
2752+
#[inline]
2753+
fn ref_from_with_trailing_elements(
2754+
bytes: &[u8],
2755+
count: usize,
2756+
) -> Result<&Self, CastError<&[u8], Self>>
2757+
where
2758+
Self: KnownLayout<PointerMetadata = usize> + Immutable,
2759+
{
2760+
let bytes = Ptr::from_ref(bytes);
2761+
let maybe_slf = bytes.try_cast_into_no_leftover::<_, BecauseImmutable>(Some(count));
2762+
match maybe_slf {
2763+
Ok(slf) => Ok(slf.bikeshed_recall_valid().as_ref()),
2764+
Err(err) => Err(err.map_src(|s| s.as_ref())),
2765+
}
2766+
}
2767+
26952768
/// Interprets the prefix of the given `bytes` as a `&[Self]` with length
26962769
/// equal to `count` without copying.
26972770
///
@@ -2742,7 +2815,7 @@ pub unsafe trait FromBytes: FromZeros {
27422815
/// #[derive(FromBytes, Immutable, KnownLayout)]
27432816
/// #[repr(C)]
27442817
/// struct ZSTy {
2745-
/// leading_sized: u16,
2818+
/// leading_sized: [u8; 2],
27462819
/// trailing_dst: [()],
27472820
/// }
27482821
///
@@ -2828,7 +2901,7 @@ pub unsafe trait FromBytes: FromZeros {
28282901
/// #[derive(FromBytes, Immutable, KnownLayout)]
28292902
/// #[repr(C)]
28302903
/// struct ZSTy {
2831-
/// leading_sized: u16,
2904+
/// leading_sized: [u8; 2],
28322905
/// trailing_dst: [()],
28332906
/// }
28342907
///
@@ -2875,6 +2948,82 @@ pub unsafe trait FromBytes: FromZeros {
28752948
<[Self]>::mut_from(bytes).ok()
28762949
}
28772950

2951+
/// Interprets the given `bytes` as a `&mut Self` with a DST length equal to
2952+
/// `count`.
2953+
///
2954+
/// This method verifies that `bytes.len() == size_of::<T>() * count` and
2955+
/// that `bytes` is aligned to `align_of::<T>()`. It also ensures that
2956+
/// `sizeof::<T>() * count` does not overflow a `usize`. If any of the
2957+
/// length, alignment, or overflow checks fail, it returns `Err`.
2958+
///
2959+
/// # Examples
2960+
///
2961+
/// ```
2962+
/// use zerocopy::FromBytes;
2963+
/// # use zerocopy_derive::*;
2964+
///
2965+
/// # #[derive(Debug, PartialEq, Eq)]
2966+
/// #[derive(KnownLayout, FromBytes, IntoBytes, Immutable)]
2967+
/// #[repr(C)]
2968+
/// struct Pixel {
2969+
/// r: u8,
2970+
/// g: u8,
2971+
/// b: u8,
2972+
/// a: u8,
2973+
/// }
2974+
///
2975+
/// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7][..];
2976+
///
2977+
/// let pixels = <[Pixel]>::mut_from_with_trailing_elements(bytes, 2).unwrap();
2978+
///
2979+
/// assert_eq!(pixels, &[
2980+
/// Pixel { r: 0, g: 1, b: 2, a: 3 },
2981+
/// Pixel { r: 4, g: 5, b: 6, a: 7 },
2982+
/// ]);
2983+
///
2984+
/// pixels[1] = Pixel { r: 0, g: 0, b: 0, a: 0 };
2985+
///
2986+
/// assert_eq!(bytes, [0, 1, 2, 3, 0, 0, 0, 0]);
2987+
/// ```
2988+
///
2989+
/// Since an explicit `count` is provided, this method supports types with
2990+
/// zero-sided trailing slice elements. Methods such as [`mut_from`] which
2991+
/// do not take an explicit count do not support such types.
2992+
///
2993+
/// ```
2994+
/// use zerocopy::*;
2995+
/// # use zerocopy_derive::*;
2996+
///
2997+
/// #[derive(FromBytes, IntoBytes, Immutable, KnownLayout)]
2998+
/// #[repr(C, packed)]
2999+
/// struct ZSTy {
3000+
/// leading_sized: [u8; 2],
3001+
/// trailing_dst: [()],
3002+
/// }
3003+
///
3004+
/// let src = &mut [85, 85][..];
3005+
/// let zsty = ZSTy::mut_from_with_trailing_elements(src, 42).unwrap();
3006+
/// assert_eq!(zsty.trailing_dst.len(), 42);
3007+
/// ```
3008+
///
3009+
/// [`mut_from`]: FromBytes::mut_from
3010+
#[must_use = "has no side effects"]
3011+
#[inline]
3012+
fn mut_from_with_trailing_elements(
3013+
bytes: &mut [u8],
3014+
count: usize,
3015+
) -> Result<&mut Self, CastError<&mut [u8], Self>>
3016+
where
3017+
Self: IntoBytes + KnownLayout<PointerMetadata = usize> + Immutable,
3018+
{
3019+
let bytes = Ptr::from_mut(bytes);
3020+
let maybe_slf = bytes.try_cast_into_no_leftover::<_, BecauseImmutable>(Some(count));
3021+
match maybe_slf {
3022+
Ok(slf) => Ok(slf.bikeshed_recall_valid().as_mut()),
3023+
Err(err) => Err(err.map_src(|s| s.as_mut())),
3024+
}
3025+
}
3026+
28783027
/// Interprets the prefix of the given `bytes` as a `&mut [Self]` with
28793028
/// length equal to `count` without copying.
28803029
///
@@ -2930,7 +3079,7 @@ pub unsafe trait FromBytes: FromZeros {
29303079
/// #[derive(FromBytes, IntoBytes, Immutable, KnownLayout)]
29313080
/// #[repr(C, packed)]
29323081
/// struct ZSTy {
2933-
/// leading_sized: u16,
3082+
/// leading_sized: [u8; 2],
29343083
/// trailing_dst: [()],
29353084
/// }
29363085
///
@@ -3021,7 +3170,7 @@ pub unsafe trait FromBytes: FromZeros {
30213170
/// #[derive(FromBytes, IntoBytes, Immutable, KnownLayout)]
30223171
/// #[repr(C, packed)]
30233172
/// struct ZSTy {
3024-
/// leading_sized: u16,
3173+
/// leading_sized: [u8; 2],
30253174
/// trailing_dst: [()],
30263175
/// }
30273176
///

0 commit comments

Comments
 (0)