Skip to content

Commit

Permalink
Remove ByteSlice::as_bytes
Browse files Browse the repository at this point in the history
TODO:
- Document pointer stability requirement
- Document Into<&[u8]>, Into<&mut [u8]> stability requirement
- Migrate slice conversions onto FromBytes methods
  • Loading branch information
joshlf committed Oct 19, 2022
1 parent e64c79d commit 2c67380
Showing 1 changed file with 38 additions and 85 deletions.
123 changes: 38 additions & 85 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ pub unsafe trait FromBytes {
where
Self: Sized,
{
if !aligned_to(bytes, mem::align_of::<Self>()) {
if !aligned_to::<_, Self>(bytes) {
return None;
}

Expand Down Expand Up @@ -367,7 +367,7 @@ pub unsafe trait FromBytes {
// SAFETY: Only the `deref_unchecked` is unsafe, and we document the
// same safety requirement on this method as is documented on
// `deref_unchecked`.
Self::unaligned_ref_from_bytes(bytes).deref_unchecked()
unsafe { Self::unaligned_ref_from_bytes(bytes).deref_unchecked() }
}

/// Converts a byte array reference to a reference to an unaligned `Self`.
Expand Down Expand Up @@ -404,7 +404,7 @@ pub unsafe trait FromBytes {
where
Self: AsBytes + Sized,
{
if !aligned_to(&*bytes, mem::align_of::<Self>()) {
if !aligned_to::<_, Self>(&*bytes) {
return None;
}

Expand Down Expand Up @@ -433,7 +433,7 @@ pub unsafe trait FromBytes {
// SAFETY: Only the `deref_mut_unchecked` is unsafe, and we document the
// same safety requirement on this method as is documented on
// `deref_mut_unchecked`.
Self::unaligned_mut_from_bytes(bytes).deref_mut_unchecked()
unsafe { Self::unaligned_mut_from_bytes(bytes).deref_mut_unchecked() }
}

/// Converts a mutable byte array reference to a mutable reference to an
Expand Down Expand Up @@ -2508,41 +2508,43 @@ where

impl<'a, B, T> LayoutVerified<B, T>
where
B: 'a + ByteSlice,
B: ByteSlice + Into<&'a [u8]>,
T: FromBytes,
{
/// Converts this `LayoutVerified` into a reference.
///
/// `into_ref` consumes the `LayoutVerified`, and returns a reference to
/// `T`.
pub fn into_ref(self) -> &'a T {
// SAFETY: This is sound because `B` is guaranteed to live for the
// lifetime `'a`, meaning that a) the returned reference cannot outlive
// the `B` from which `self` was constructed and, b) no mutable methods
// on that `B` can be called during the lifetime of the returned
// reference. See the documentation on `deref_helper` for what
// invariants we are required to uphold.
unsafe { self.deref_helper() }
let bytes = self.0.into();
// SAFETY: `LayoutVerified` upholds the invariant that `.0`'s length is
// equal to `size_of::<T>()`. `size_of::<ByteArray<T>>() ==
// size_of::<T>()`, so this call is sound.
let byte_array = unsafe { ByteArray::from_slice_unchecked(bytes) };
// SAFETY: `LayoutVerified` upholds the invariant that `.0` satisfies
// `T`'s alignment requirement.
unsafe { T::ref_from_bytes_unchecked(byte_array) }
}
}

impl<'a, B, T> LayoutVerified<B, T>
where
B: 'a + ByteSliceMut,
B: ByteSliceMut + Into<&'a mut [u8]>,
T: FromBytes + AsBytes,
{
/// Converts this `LayoutVerified` into a mutable reference.
///
/// `into_mut` consumes the `LayoutVerified`, and returns a mutable
/// reference to `T`.
pub fn into_mut(mut self) -> &'a mut T {
// SAFETY: This is sound because `B` is guaranteed to live for the
// lifetime `'a`, meaning that a) the returned reference cannot outlive
// the `B` from which `self` was constructed and, b) no other methods -
// mutable or immutable - on that `B` can be called during the lifetime
// of the returned reference. See the documentation on
// `deref_mut_helper` for what invariants we are required to uphold.
unsafe { self.deref_mut_helper() }
pub fn into_mut(self) -> &'a mut T {
let bytes = self.0.into();
// SAFETY: `LayoutVerified` upholds the invariant that `.0`'s length is
// equal to `size_of::<T>()`. `size_of::<ByteArray<T>>() ==
// size_of::<T>()`, so this call is sound.
let byte_array = unsafe { ByteArray::from_mut_slice_unchecked(bytes) };
// SAFETY: `LayoutVerified` upholds the invariant that `.0` satisfies
// `T`'s alignment requirement.
unsafe { T::mut_from_bytes_unchecked(byte_array) }
}
}

Expand Down Expand Up @@ -2587,56 +2589,6 @@ where
}
}

impl<B, T> LayoutVerified<B, T>
where
B: ByteSlice,
T: FromBytes,
{
/// Creates an immutable reference to `T` with a specific lifetime.
///
/// # Safety
///
/// The type bounds on this method guarantee that it is safe to create an
/// immutable reference to `T` from `self`. However, since the lifetime `'a`
/// is not required to be shorter than the lifetime of the reference to
/// `self`, the caller must guarantee that the lifetime `'a` is valid for
/// this reference. In particular, the referent must exist for all of `'a`,
/// and no mutable references to the same memory may be constructed during
/// `'a`.
unsafe fn deref_helper<'a>(&self) -> &'a T {
// TODO(#61): Add a "SAFETY" comment and remove this `allow`.
#[allow(clippy::undocumented_unsafe_blocks)]
unsafe {
&*self.0.as_ptr().cast::<T>()
}
}
}

impl<B, T> LayoutVerified<B, T>
where
B: ByteSliceMut,
T: FromBytes + AsBytes,
{
/// Creates a mutable reference to `T` with a specific lifetime.
///
/// # Safety
///
/// The type bounds on this method guarantee that it is safe to create a
/// mutable reference to `T` from `self`. However, since the lifetime `'a`
/// is not required to be shorter than the lifetime of the reference to
/// `self`, the caller must guarantee that the lifetime `'a` is valid for
/// this reference. In particular, the referent must exist for all of `'a`,
/// and no other references - mutable or immutable - to the same memory may
/// be constructed during `'a`.
unsafe fn deref_mut_helper<'a>(&mut self) -> &'a mut T {
// TODO(#61): Add a "SAFETY" comment and remove this `allow`.
#[allow(clippy::undocumented_unsafe_blocks)]
unsafe {
&mut *self.0.as_mut_ptr().cast::<T>()
}
}
}

impl<B, T> LayoutVerified<B, [T]>
where
B: ByteSlice,
Expand Down Expand Up @@ -2827,13 +2779,13 @@ where
type Target = T;
#[inline]
fn deref(&self) -> &T {
// SAFETY: This is sound because the lifetime of `self` is the same as
// the lifetime of the return value, meaning that a) the returned
// reference cannot outlive `self` and, b) no mutable methods on `self`
// can be called during the lifetime of the returned reference. See the
// documentation on `deref_helper` for what invariants we are required
// to uphold.
unsafe { self.deref_helper() }
// SAFETY: `LayoutVerified` upholds the invariant that `.0`'s length is
// equal to `size_of::<T>()`. `size_of::<ByteArray<T>>() ==
// size_of::<T>()`, so this call is sound.
let byte_array = unsafe { ByteArray::from_slice_unchecked(self.0.deref()) };
// SAFETY: `LayoutVerified` upholds the invariant that `.0` satisfies
// `T`'s alignment requirement.
unsafe { T::ref_from_bytes_unchecked(byte_array) }
}
}

Expand All @@ -2844,13 +2796,13 @@ where
{
#[inline]
fn deref_mut(&mut self) -> &mut T {
// SAFETY: This is sound because the lifetime of `self` is the same as
// the lifetime of the return value, meaning that a) the returned
// reference cannot outlive `self` and, b) no other methods on `self`
// can be called during the lifetime of the returned reference. See the
// documentation on `deref_mut_helper` for what invariants we are
// required to uphold.
unsafe { self.deref_mut_helper() }
// SAFETY: `LayoutVerified` upholds the invariant that `.0`'s length is
// equal to `size_of::<T>()`. `size_of::<ByteArray<T>>() ==
// size_of::<T>()`, so this call is sound.
let byte_array = unsafe { ByteArray::from_mut_slice_unchecked(self.0.deref_mut()) };
// SAFETY: `LayoutVerified` upholds the invariant that `.0` satisfies
// `T`'s alignment requirement.
unsafe { T::mut_from_bytes_unchecked(byte_array) }
}
}

Expand Down Expand Up @@ -3059,6 +3011,7 @@ mod sealed {
///
/// [`Vec<u8>`]: std::vec::Vec
/// [`split_at`]: crate::ByteSlice::split_at
// TODO(joshlf): Require that Into<&[u8]> and Into<&mut [u8]> are stable.
pub unsafe trait ByteSlice: Deref<Target = [u8]> + Sized + self::sealed::Sealed {
/// Gets a raw pointer to the first byte in the slice.
#[inline]
Expand Down

0 comments on commit 2c67380

Please sign in to comment.