diff --git a/src/deprecated.rs b/src/deprecated.rs index f7922f2b54..d972aef6a3 100644 --- a/src/deprecated.rs +++ b/src/deprecated.rs @@ -63,3 +63,53 @@ where self.into_mut() } } + +impl Ref +where + B: SplitByteSlice, + T: NoCell, +{ + #[deprecated(since = "0.8.0", note = "replaced by `Ref::with_trailing_elements_from_prefix`")] + #[must_use = "has no side effects"] + #[doc(hidden)] + #[inline] + pub fn new_slice_from_prefix(bytes: B, count: usize) -> Option<(Ref, B)> { + Ref::with_trailing_elements_from_prefix(bytes, count) + } + + #[deprecated(since = "0.8.0", note = "replaced by `Ref::with_trailing_elements_from_suffix`")] + #[must_use = "has no side effects"] + #[doc(hidden)] + #[inline] + pub fn new_slice_from_suffix(bytes: B, count: usize) -> Option<(B, Ref)> { + Ref::with_trailing_elements_from_suffix(bytes, count) + } +} + +impl Ref +where + B: SplitByteSlice, + T: Unaligned + NoCell, +{ + #[deprecated( + since = "0.8.0", + note = "replaced by `Ref::with_trailing_elements_unaligned_from_prefix`" + )] + #[doc(hidden)] + #[must_use = "has no side effects"] + #[inline(always)] + pub fn new_slice_unaligned_from_prefix(bytes: B, count: usize) -> Option<(Ref, B)> { + Ref::with_trailing_elements_unaligned_from_prefix(bytes, count) + } + + #[deprecated( + since = "0.8.0", + note = "replaced by `Ref::with_trailing_elements_unaligned_from_suffix`" + )] + #[doc(hidden)] + #[must_use = "has no side effects"] + #[inline(always)] + pub fn new_slice_unaligned_from_suffix(bytes: B, count: usize) -> Option<(B, Ref)> { + Ref::with_trailing_elements_unaligned_from_suffix(bytes, count) + } +} diff --git a/src/lib.rs b/src/lib.rs index bb69a92275..c1b4c7b913 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1065,8 +1065,9 @@ pub unsafe trait KnownLayout { where Self: Sized; - /// `()` for sized types and `usize` for slice DSTs. - #[doc(hidden)] + /// The type of metadata stored in a pointer to `Self`. + /// + /// This is `()` for sized types and `usize` for slice DSTs. type PointerMetadata: PointerMetadata; #[doc(hidden)] @@ -2529,11 +2530,25 @@ pub unsafe trait FromBytes: FromZeros { /// ``` #[must_use = "has no side effects"] #[inline] + fn from_prefix_with_trailing_elements(bytes: &[u8], count: usize) -> Option<(&Self, &[u8])> + where + Self: KnownLayout + NoCell, + { + Ref::<_, Self>::with_trailing_elements_from_prefix(bytes, count) + .map(|(r, b)| (r.into_ref(), b)) + } + + #[deprecated( + since = "0.8.0", + note = "renamed to `FromBytes::from_prefix_with_trailing_elements`" + )] + #[doc(hidden)] + #[inline] fn slice_from_prefix(bytes: &[u8], count: usize) -> Option<(&[Self], &[u8])> where Self: Sized + NoCell, { - Ref::<_, [Self]>::new_slice_from_prefix(bytes, count).map(|(r, b)| (r.into_ref(), b)) + <[Self]>::from_prefix_with_trailing_elements(bytes, count) } /// Interprets the suffix of the given `bytes` as a `&[Self]` with length @@ -2580,63 +2595,36 @@ pub unsafe trait FromBytes: FromZeros { /// ``` #[must_use = "has no side effects"] #[inline] + fn from_suffix_with_trailing_elements(bytes: &[u8], count: usize) -> Option<(&[u8], &Self)> + where + Self: KnownLayout + NoCell, + { + Ref::<_, Self>::with_trailing_elements_from_suffix(bytes, count) + .map(|(b, r)| (b, r.into_ref())) + } + + #[deprecated( + since = "0.8.0", + note = "renamed to `FromBytes::from_prefix_with_trailing_elements`" + )] + #[doc(hidden)] + #[inline] fn slice_from_suffix(bytes: &[u8], count: usize) -> Option<(&[u8], &[Self])> where Self: Sized + NoCell, { - Ref::<_, [Self]>::new_slice_from_suffix(bytes, count).map(|(b, r)| (b, r.into_ref())) + <[Self]>::from_suffix_with_trailing_elements(bytes, count) } - /// Interprets the given `bytes` as a `&mut [Self]` without copying. - /// - /// If `bytes.len() % size_of::() != 0` or `bytes` is not aligned to - /// `align_of::()`, this returns `None`. - /// - /// If you need to convert a specific number of slice elements, see - /// [`mut_slice_from_prefix`](FromBytes::mut_slice_from_prefix) or - /// [`mut_slice_from_suffix`](FromBytes::mut_slice_from_suffix). - /// - /// # Panics - /// - /// If `T` is a zero-sized type. - /// - /// # Examples - /// - /// ``` - /// use zerocopy::FromBytes; - /// # use zerocopy_derive::*; - /// - /// # #[derive(Debug, PartialEq, Eq)] - /// #[derive(FromBytes, IntoBytes, NoCell)] - /// #[repr(C)] - /// struct Pixel { - /// r: u8, - /// g: u8, - /// b: u8, - /// a: u8, - /// } - /// - /// // These bytes encode two `Pixel`s. - /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7][..]; - /// - /// let pixels = Pixel::mut_slice_from(bytes).unwrap(); - /// - /// assert_eq!(pixels, &[ - /// Pixel { r: 0, g: 1, b: 2, a: 3 }, - /// Pixel { r: 4, g: 5, b: 6, a: 7 }, - /// ]); - /// - /// pixels[1] = Pixel { r: 0, g: 0, b: 0, a: 0 }; - /// - /// assert_eq!(bytes, [0, 1, 2, 3, 0, 0, 0, 0]); - /// ``` + #[deprecated(since = "0.8.0", note = "`FromBytes::mut_from` now supports slices")] #[must_use = "has no side effects"] + #[doc(hidden)] #[inline] fn mut_slice_from(bytes: &mut [u8]) -> Option<&mut [Self]> where Self: Sized + IntoBytes + NoCell, { - Ref::<_, [Self]>::new(bytes).map(|r| r.into_mut()) + <[Self]>::mut_from(bytes) } /// Interprets the prefix of the given `bytes` as a `&mut [Self]` with @@ -2688,11 +2676,28 @@ pub unsafe trait FromBytes: FromZeros { /// ``` #[must_use = "has no side effects"] #[inline] - fn mut_slice_from_prefix(bytes: &mut [u8], count: usize) -> Option<(&mut [Self], &mut [u8])> + fn mut_from_prefix_with_trailing_elements( + bytes: &mut [u8], + count: usize, + ) -> Option<(&mut Self, &mut [u8])> where - Self: Sized + IntoBytes + NoCell, + Self: IntoBytes + KnownLayout + NoCell, + { + Ref::<_, Self>::with_trailing_elements_from_prefix(bytes, count) + .map(|(r, b)| (r.into_mut(), b)) + } + + #[deprecated( + since = "0.8.0", + note = "renamed to `FromBytes::mut_from_prefix_with_trailing_elements`" + )] + #[doc(hidden)] + #[inline] + fn mut_slice_from_prefix(bytes: &[u8], count: usize) -> Option<(&[Self], &[u8])> + where + Self: Sized + NoCell, { - Ref::<_, [Self]>::new_slice_from_prefix(bytes, count).map(|(r, b)| (r.into_mut(), b)) + <[Self]>::from_prefix_with_trailing_elements(bytes, count) } /// Interprets the suffix of the given `bytes` as a `&mut [Self]` with length @@ -2744,11 +2749,28 @@ pub unsafe trait FromBytes: FromZeros { /// ``` #[must_use = "has no side effects"] #[inline] + fn mut_from_suffix_with_trailing_elements( + bytes: &mut [u8], + count: usize, + ) -> Option<(&mut [u8], &mut Self)> + where + Self: IntoBytes + KnownLayout + NoCell, + { + Ref::<_, Self>::with_trailing_elements_from_suffix(bytes, count) + .map(|(b, r)| (b, r.into_mut())) + } + + #[deprecated( + since = "0.8.0", + note = "renamed to `FromBytes::mut_from_suffix_with_trailing_elements`" + )] + #[doc(hidden)] + #[inline] fn mut_slice_from_suffix(bytes: &mut [u8], count: usize) -> Option<(&mut [u8], &mut [Self])> where Self: Sized + IntoBytes + NoCell, { - Ref::<_, [Self]>::new_slice_from_suffix(bytes, count).map(|(b, r)| (b, r.into_mut())) + <[Self]>::mut_from_suffix_with_trailing_elements(bytes, count) } /// Reads a copy of `Self` from `bytes`. @@ -5084,58 +5106,44 @@ where } } -impl Ref +impl Ref where B: SplitByteSlice, - T: NoCell, + T: KnownLayout + NoCell + ?Sized, { - /// Constructs a new `Ref` of a slice type from the prefix of a byte slice. - /// - /// `new_slice_from_prefix` verifies that `bytes.len() >= size_of::() * - /// count` and that `bytes` is aligned to `align_of::()`. It consumes the - /// first `size_of::() * count` bytes from `bytes` to construct a `Ref`, - /// and returns the remaining bytes to the caller. It also ensures that - /// `sizeof::() * count` does not overflow a `usize`. If any of the - /// length, alignment, or overflow checks fail, it returns `None`. - /// - /// # Panics - /// - /// `new_slice_from_prefix` panics if `T` is a zero-sized type. - #[must_use = "has no side effects"] + // TODO(#29), TODO(#871): Pick a name and make this public. Make sure to + // update references to this name in `#[deprecated]` attributes elsewhere. + #[doc(hidden)] #[inline] - pub fn new_slice_from_prefix(bytes: B, count: usize) -> Option<(Ref, B)> { - let expected_len = match mem::size_of::().checked_mul(count) { + pub fn with_trailing_elements_from_prefix(bytes: B, count: usize) -> Option<(Ref, B)> { + let expected_len = match count.size_for_metadata(T::LAYOUT) { Some(len) => len, None => return None, }; if bytes.len() < expected_len { return None; } - let (prefix, bytes) = try_split_at(bytes, expected_len)?; + let (prefix, bytes) = bytes.split_at(expected_len); Self::new(prefix).map(move |l| (l, bytes)) } +} - /// Constructs a new `Ref` of a slice type from the suffix of a byte slice. - /// - /// `new_slice_from_suffix` verifies that `bytes.len() >= size_of::() * - /// count` and that `bytes` is aligned to `align_of::()`. It consumes the - /// last `size_of::() * count` bytes from `bytes` to construct a `Ref`, - /// and returns the preceding bytes to the caller. It also ensures that - /// `sizeof::() * count` does not overflow a `usize`. If any of the - /// length, alignment, or overflow checks fail, it returns `None`. - /// - /// # Panics - /// - /// `new_slice_from_suffix` panics if `T` is a zero-sized type. - #[must_use = "has no side effects"] +impl Ref +where + B: SplitByteSlice, + T: KnownLayout + NoCell + ?Sized, +{ + // TODO(#29), TODO(#871): Pick a name and make this public. Make sure to + // update references to this name in `#[deprecated]` attributes elsewhere. + #[doc(hidden)] #[inline] - pub fn new_slice_from_suffix(bytes: B, count: usize) -> Option<(B, Ref)> { - let expected_len = match mem::size_of::().checked_mul(count) { + pub fn with_trailing_elements_from_suffix(bytes: B, count: usize) -> Option<(B, Ref)> { + let expected_len = match count.size_for_metadata(T::LAYOUT) { Some(len) => len, None => return None, }; let split_at = bytes.len().checked_sub(expected_len)?; - let (bytes, suffix) = try_split_at(bytes, split_at)?; + let (bytes, suffix) = bytes.split_at(split_at); Self::new(suffix).map(move |l| (bytes, l)) } } @@ -5188,46 +5196,37 @@ where } } -impl Ref +impl Ref where B: SplitByteSlice, - T: Unaligned + NoCell, + T: KnownLayout + Unaligned + NoCell + ?Sized, { - /// Constructs a new `Ref` of a slice type with no alignment requirement - /// from the prefix of a byte slice. - /// - /// `new_slice_from_prefix` verifies that `bytes.len() >= size_of::() * - /// count`. It consumes the first `size_of::() * count` bytes from - /// `bytes` to construct a `Ref`, and returns the remaining bytes to the - /// caller. It also ensures that `sizeof::() * count` does not overflow a - /// `usize`. If either the length, or overflow checks fail, it returns - /// `None`. - /// - /// # Panics - /// - /// `new_slice_unaligned_from_prefix` panics if `T` is a zero-sized type. - #[must_use = "has no side effects"] - #[inline(always)] - pub fn new_slice_unaligned_from_prefix(bytes: B, count: usize) -> Option<(Ref, B)> { - Ref::new_slice_from_prefix(bytes, count) + // TODO(#29), TODO(#871): Pick a name and make this public. Make sure to + // update references to this name in `#[deprecated]` attributes elsewhere. + #[doc(hidden)] + #[inline] + pub fn with_trailing_elements_unaligned_from_prefix( + bytes: B, + count: usize, + ) -> Option<(Ref, B)> { + Self::with_trailing_elements_from_prefix(bytes, count) } +} - /// Constructs a new `Ref` of a slice type with no alignment requirement - /// from the suffix of a byte slice. - /// - /// `new_slice_from_suffix` verifies that `bytes.len() >= size_of::() * - /// count`. It consumes the last `size_of::() * count` bytes from `bytes` - /// to construct a `Ref`, and returns the remaining bytes to the caller. It - /// also ensures that `sizeof::() * count` does not overflow a `usize`. - /// If either the length, or overflow checks fail, it returns `None`. - /// - /// # Panics - /// - /// `new_slice_unaligned_from_suffix` panics if `T` is a zero-sized type. - #[must_use = "has no side effects"] - #[inline(always)] - pub fn new_slice_unaligned_from_suffix(bytes: B, count: usize) -> Option<(B, Ref)> { - Ref::new_slice_from_suffix(bytes, count) +impl Ref +where + B: SplitByteSlice, + T: KnownLayout + Unaligned + NoCell + ?Sized, +{ + // TODO(#29), TODO(#871): Pick a name and make this public. Make sure to + // update references to this name in `#[deprecated]` attributes elsewhere. + #[doc(hidden)] + #[inline] + pub fn with_trailing_elements_unaligned_from_suffix( + bytes: B, + count: usize, + ) -> Option<(B, Ref)> { + Self::with_trailing_elements_from_suffix(bytes, count) } }