// SPDX-License-Identifier: (BSD-2-Clause OR Apache-2.0) OR MIT//// Copyright 2024 The Fuchsia Authors//// Licensed under the 2-Clause BSD License <LICENSE-BSD or// https://opensource.org/license/bsd-2-clause>, Apache License, Version 2.0// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.// This file may not be copied, modified, or distributed except according to// those terms.use super::*;use crate::pointer::{ BecauseInvariantsEq, BecauseMutationCompatible, MutationCompatible, TransmuteFromPtr,}; mod def { use core::marker::PhantomData; use crate::{ ByteSlice, ByteSliceMut, CloneableByteSlice, CopyableByteSlice, IntoByteSlice, IntoByteSliceMut, }; /// A typed reference derived from a byte slice. /// /// A `Ref<B, T>` is a reference to a `T` which is stored in a byte slice, `B`. /// Unlike a native reference (`&T` or `&mut T`), `Ref<B, T>` has the same /// mutability as the byte slice it was constructed from (`B`). /// /// # Examples /// /// `Ref` can be used to treat a sequence of bytes as a structured type, and /// to read and write the fields of that type as if the byte slice reference /// were simply a reference to that type. /// /// ```rust /// use zerocopy::*; /// # use zerocopy_derive::*; /// /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)] /// #[repr(C)] /// struct UdpHeader { /// src_port: [u8; 2], /// dst_port: [u8; 2], /// length: [u8; 2], /// checksum: [u8; 2], /// } /// /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)] /// #[repr(C, packed)] /// struct UdpPacket { /// header: UdpHeader, /// body: [u8], /// } /// /// impl UdpPacket { /// pub fn parse<B: ByteSlice>(bytes: B) -> Option<Ref<B, UdpPacket>> { /// Ref::from_bytes(bytes).ok() /// } /// } /// ``` pub struct Ref<B, T: ?Sized>( // INVARIANTS: The referent (via `.deref`, `.deref_mut`, `.into`) byte // slice is aligned to `T`'s alignment and its size corresponds to a // valid size for `T`. B, PhantomData<T>, ); impl<B, T: ?Sized> Ref<B, T> { /// Constructs a new `Ref`. /// /// # Safety /// /// `bytes` dereferences (via [`deref`], [`deref_mut`], and [`into`]) to /// a byte slice which is aligned to `T`'s alignment and whose size is a /// valid size for `T`. /// /// [`deref`]: core::ops::Deref::deref /// [`deref_mut`]: core::ops::DerefMut::deref_mut /// [`into`]: core::convert::Into::into pub(crate) unsafe fn new_unchecked(bytes: B) -> Ref<B, T> { // INVARIANTS: The caller has promised that `bytes`'s referent is // validly-aligned and has a valid size. Ref(bytes, PhantomData) } } impl<B: ByteSlice, T: ?Sized> Ref<B, T> { /// Access the byte slice as a [`ByteSlice`]. /// /// # Safety /// /// The caller promises not to call methods on the returned /// [`ByteSlice`] other than `ByteSlice` methods (for example, via /// `Any::downcast_ref`). /// /// `as_byte_slice` promises to return a `ByteSlice` whose referent is /// validly-aligned for `T` and has a valid size for `T`. pub(crate) unsafe fn as_byte_slice(&self) -> &impl ByteSlice { // INVARIANTS: The caller promises not to call methods other than // those on `ByteSlice`. Since `B: ByteSlice`, dereference stability // guarantees that calling `ByteSlice` methods will not change the // address or length of `self.0`'s referent. // // SAFETY: By invariant on `self.0`, the alignment and size // post-conditions are upheld. &self.0 } } impl<B: ByteSliceMut, T: ?Sized> Ref<B, T> { /// Access the byte slice as a [`ByteSliceMut`]. /// /// # Safety /// /// The caller promises not to call methods on the returned /// [`ByteSliceMut`] other than `ByteSliceMut` methods (for example, via /// `Any::downcast_mut`). /// /// `as_byte_slice` promises to return a `ByteSlice` whose referent is /// validly-aligned for `T` and has a valid size for `T`. pub(crate) unsafe fn as_byte_slice_mut(&mut self) -> &mut impl ByteSliceMut { // INVARIANTS: The caller promises not to call methods other than // those on `ByteSliceMut`. Since `B: ByteSlice`, dereference // stability guarantees that calling `ByteSlice` methods will not // change the address or length of `self.0`'s referent. // // SAFETY: By invariant on `self.0`, the alignment and size // post-conditions are upheld. &mut self.0 } } impl<'a, B: IntoByteSlice<'a>, T: ?Sized> Ref<B, T> { /// Access the byte slice as an [`IntoByteSlice`]. /// /// # Safety /// /// The caller promises not to call methods on the returned /// [`IntoByteSlice`] other than `IntoByteSlice` methods (for example, /// via `Any::downcast_ref`). /// /// `as_byte_slice` promises to return a `ByteSlice` whose referent is /// validly-aligned for `T` and has a valid size for `T`. pub(crate) unsafe fn into_byte_slice(self) -> impl IntoByteSlice<'a> { // INVARIANTS: The caller promises not to call methods other than // those on `IntoByteSlice`. Since `B: ByteSlice`, dereference // stability guarantees that calling `ByteSlice` methods will not // change the address or length of `self.0`'s referent. // // SAFETY: By invariant on `self.0`, the alignment and size // post-conditions are upheld. self.0 } } impl<'a, B: IntoByteSliceMut<'a>, T: ?Sized> Ref<B, T> { /// Access the byte slice as an [`IntoByteSliceMut`]. /// /// # Safety /// /// The caller promises not to call methods on the returned /// [`IntoByteSliceMut`] other than `IntoByteSliceMut` methods (for /// example, via `Any::downcast_mut`). /// /// `as_byte_slice` promises to return a `ByteSlice` whose referent is /// validly-aligned for `T` and has a valid size for `T`. pub(crate) unsafe fn into_byte_slice_mut(self) -> impl IntoByteSliceMut<'a> { // INVARIANTS: The caller promises not to call methods other than // those on `IntoByteSliceMut`. Since `B: ByteSlice`, dereference // stability guarantees that calling `ByteSlice` methods will not // change the address or length of `self.0`'s referent. // // SAFETY: By invariant on `self.0`, the alignment and size // post-conditions are upheld. self.0 } } impl<B: CloneableByteSlice + Clone, T: ?Sized> Clone for Ref<B, T> { #[inline] fn clone(&self) -> Ref<B, T> { // INVARIANTS: Since `B: CloneableByteSlice`, `self.0.clone()` has // the same address and length as `self.0`. Since `self.0` upholds // the field invariants, so does `self.0.clone()`. Ref(self.0.clone(), PhantomData) } } // INVARIANTS: Since `B: CopyableByteSlice`, the copied `Ref`'s `.0` has the // same address and length as the original `Ref`'s `.0`. Since the original // upholds the field invariants, so does the copy. impl<B: CopyableByteSlice + Copy, T: ?Sized> Copy for Ref<B, T> {}} #[allow(unreachable_pub)] // This is a false positive on our MSRV toolchain.pub use def::Ref; use crate::pointer::{ invariant::{Aligned, BecauseExclusive, Initialized, Unaligned, Valid}, BecauseRead, PtrInner,}; impl<B, T> Ref<B, T>where B: ByteSlice,{ #[must_use = "has no side effects"] pub(crate) fn sized_from(bytes: B) -> Result<Ref<B, T>, CastError<B, T>> { if bytes.len() != mem::size_of::<T>() { return Err(SizeError::new(bytes).into()); } if let Err(err) = util::validate_aligned_to::<_, T>(bytes.deref()) { return Err(err.with_src(bytes).into()); } // SAFETY: We just validated size and alignment. Ok(unsafe { Ref::new_unchecked(bytes) }) }} impl<B, T> Ref<B, T>where B: SplitByteSlice,{ #[must_use = "has no side effects"] pub(crate) fn sized_from_prefix(bytes: B) -> Result<(Ref<B, T>, B), CastError<B, T>> { if bytes.len() < mem::size_of::<T>() { return Err(SizeError::new(bytes).into()); } if let Err(err) = util::validate_aligned_to::<_, T>(bytes.deref()) { return Err(err.with_src(bytes).into()); } let (bytes, suffix) = bytes.split_at(mem::size_of::<T>()).map_err( #[inline(always)] |b| SizeError::new(b).into(), )?; // SAFETY: We just validated alignment and that `bytes` is at least as // large as `T`. `bytes.split_at(mem::size_of::<T>())?` ensures that the // new `bytes` is exactly the size of `T`. By safety postcondition on // `SplitByteSlice::split_at` we can rely on `split_at` to produce the // correct `bytes` and `suffix`. let r = unsafe { Ref::new_unchecked(bytes) }; Ok((r, suffix)) } #[must_use = "has no side effects"] pub(crate) fn sized_from_suffix(bytes: B) -> Result<(B, Ref<B, T>), CastError<B, T>> { let bytes_len = bytes.len(); let split_at = if let Some(split_at) = bytes_len.checked_sub(mem::size_of::<T>()) { split_at } else { return Err(SizeError::new(bytes).into()); }; let (prefix, bytes) = bytes.split_at(split_at).map_err(|b| SizeError::new(b).into())?; if let Err(err) = util::validate_aligned_to::<_, T>(bytes.deref()) { return Err(err.with_src(bytes).into()); } // SAFETY: Since `split_at` is defined as `bytes_len - size_of::<T>()`, // the `bytes` which results from `let (prefix, bytes) = // bytes.split_at(split_at)?` has length `size_of::<T>()`. After // constructing `bytes`, we validate that it has the proper alignment. // By safety postcondition on `SplitByteSlice::split_at` we can rely on // `split_at` to produce the correct `prefix` and `bytes`. let r = unsafe { Ref::new_unchecked(bytes) }; Ok((prefix, r)) }} impl<B, T> Ref<B, T>where B: ByteSlice, T: KnownLayout + Immutable + ?Sized,{ /// Constructs a `Ref` from a byte slice. /// /// If the length of `source` is not a [valid size of `T`][valid-size], or /// if `source` is not appropriately aligned for `T`, this returns `Err`. If /// [`T: Unaligned`][t-unaligned], you can [infallibly discard the alignment /// error][size-error-from]. /// /// `T` may be a sized type, a slice, or a [slice DST][slice-dst]. /// /// [valid-size]: crate::KnownLayout#what-is-a-valid-size /// [t-unaligned]: crate::Unaligned /// [size-error-from]: error/struct.SizeError.html#method.from-1 /// [slice-dst]: KnownLayout#dynamically-sized-types /// /// # Compile-Time Assertions /// /// This method cannot yet be used on unsized types whose dynamically-sized /// component is zero-sized. Attempting to use this method on such types /// results in a compile-time assertion error; e.g.: /// /// ```compile_fail,E0080 /// use zerocopy::*; /// # use zerocopy_derive::*; /// /// #[derive(Immutable, KnownLayout)] /// #[repr(C)] /// struct ZSTy { /// leading_sized: u16, /// trailing_dst: [()], /// } /// /// let _ = Ref::<_, ZSTy>::from_bytes(&b"UU"[..]); // ⚠ Compile Error! /// ``` #[must_use = "has no side effects"] #[inline] pub fn from_bytes(source: B) -> Result<Ref<B, T>, CastError<B, T>> { static_assert_dst_is_not_zst!(T); if let Err(e) = Ptr::from_ref(source.deref()).try_cast_into_no_leftover::<T, BecauseImmutable>(None) { return Err(e.with_src(()).with_src(source)); } // SAFETY: `try_cast_into_no_leftover` validates size and alignment. Ok(unsafe { Ref::new_unchecked(source) }) }} impl<B, T> Ref<B, T>where B: SplitByteSlice, T: KnownLayout + Immutable + ?Sized,{ /// Constructs a `Ref` from the prefix of a byte slice. /// /// This method computes the [largest possible size of `T`][valid-size] that /// can fit in the leading bytes of `source`, then attempts to return both a /// `Ref` to those bytes, and a reference to the remaining bytes. If there /// are insufficient bytes, or if `source` is not appropriately aligned, /// this returns `Err`. If [`T: Unaligned`][t-unaligned], you can /// [infallibly discard the alignment error][size-error-from]. /// /// `T` may be a sized type, a slice, or a [slice DST][slice-dst]. /// /// [valid-size]: crate::KnownLayout#what-is-a-valid-size /// [t-unaligned]: crate::Unaligned /// [size-error-from]: error/struct.SizeError.html#method.from-1 /// [slice-dst]: KnownLayout#dynamically-sized-types /// /// # Compile-Time Assertions /// /// This method cannot yet be used on unsized types whose dynamically-sized /// component is zero-sized. Attempting to use this method on such types /// results in a compile-time assertion error; e.g.: /// /// ```compile_fail,E0080 /// use zerocopy::*; /// # use zerocopy_derive::*; /// /// #[derive(Immutable, KnownLayout)] /// #[repr(C)] /// struct ZSTy { /// leading_sized: u16, /// trailing_dst: [()], /// } /// /// let _ = Ref::<_, ZSTy>::from_prefix(&b"UU"[..]); // ⚠ Compile Error! /// ``` #[must_use = "has no side effects"] #[inline] pub fn from_prefix(source: B) -> Result<(Ref<B, T>, B), CastError<B, T>> { static_assert_dst_is_not_zst!(T); let remainder = match Ptr::from_ref(source.deref()) .try_cast_into::<T, BecauseImmutable>(CastType::Prefix, None) { Ok((_, remainder)) => remainder, Err(e) => { return Err(e.with_src(()).with_src(source)); } }; // SAFETY: `remainder` is constructed as a subset of `source`, and so it // cannot have a larger size than `source`. Both of their `len` methods // measure bytes (`source` deref's to `[u8]`, and `remainder` is a // `Ptr<[u8]>`), so `source.len() >= remainder.len()`. Thus, this cannot // underflow. #[allow(unstable_name_collisions)] let split_at = unsafe { source.len().unchecked_sub(remainder.len()) }; let (bytes, suffix) = source.split_at(split_at).map_err(|b| SizeError::new(b).into())?; // SAFETY: `try_cast_into` validates size and alignment, and returns a // `split_at` that indicates how many bytes of `source` correspond to a // valid `T`. By safety postcondition on `SplitByteSlice::split_at` we // can rely on `split_at` to produce the correct `source` and `suffix`. let r = unsafe { Ref::new_unchecked(bytes) }; Ok((r, suffix)) } /// Constructs a `Ref` from the suffix of a byte slice. /// /// This method computes the [largest possible size of `T`][valid-size] that /// can fit in the trailing bytes of `source`, then attempts to return both /// a `Ref` to those bytes, and a reference to the preceding bytes. If there /// are insufficient bytes, or if that suffix of `source` is not /// appropriately aligned, this returns `Err`. If [`T: /// Unaligned`][t-unaligned], you can [infallibly discard the alignment /// error][size-error-from]. /// /// `T` may be a sized type, a slice, or a [slice DST][slice-dst]. /// /// [valid-size]: crate::KnownLayout#what-is-a-valid-size /// [t-unaligned]: crate::Unaligned /// [size-error-from]: error/struct.SizeError.html#method.from-1 /// [slice-dst]: KnownLayout#dynamically-sized-types /// /// # Compile-Time Assertions /// /// This method cannot yet be used on unsized types whose dynamically-sized /// component is zero-sized. Attempting to use this method on such types /// results in a compile-time assertion error; e.g.: /// /// ```compile_fail,E0080 /// use zerocopy::*; /// # use zerocopy_derive::*; /// /// #[derive(Immutable, KnownLayout)] /// #[repr(C)] /// struct ZSTy { /// leading_sized: u16, /// trailing_dst: [()], /// } /// /// let _ = Ref::<_, ZSTy>::from_suffix(&b"UU"[..]); // ⚠ Compile Error! /// ``` #[must_use = "has no side effects"] #[inline] pub fn from_suffix(source: B) -> Result<(B, Ref<B, T>), CastError<B, T>> { static_assert_dst_is_not_zst!(T); let remainder = match Ptr::from_ref(source.deref()) .try_cast_into::<T, BecauseImmutable>(CastType::Suffix, None) { Ok((_, remainder)) => remainder, Err(e) => { let e = e.with_src(()); return Err(e.with_src(source)); } }; let split_at = remainder.len(); let (prefix, bytes) = source.split_at(split_at).map_err(|b| SizeError::new(b).into())?; // SAFETY: `try_cast_into` validates size and alignment, and returns a // `split_at` that indicates how many bytes of `source` correspond to a // valid `T`. By safety postcondition on `SplitByteSlice::split_at` we // can rely on `split_at` to produce the correct `prefix` and `bytes`. let r = unsafe { Ref::new_unchecked(bytes) }; Ok((prefix, r)) }} impl<B, T> Ref<B, T>where B: ByteSlice, T: KnownLayout<PointerMetadata = usize> + Immutable + ?Sized,{ /// Constructs a `Ref` from the given bytes with DST length equal to `count` /// without copying. /// /// This method attempts to return a `Ref` to the prefix of `source` /// interpreted as a `T` with `count` trailing elements, and a reference to /// the remaining bytes. If the length of `source` is not equal to the size /// of `Self` with `count` elements, or if `source` is not appropriately /// aligned, this returns `Err`. If [`T: Unaligned`][t-unaligned], you can /// [infallibly discard the alignment error][size-error-from]. /// /// [t-unaligned]: crate::Unaligned /// [size-error-from]: error/struct.SizeError.html#method.from-1 /// /// # Compile-Time Assertions /// /// This method cannot yet be used on unsized types whose dynamically-sized /// component is zero-sized. Attempting to use this method on such types /// results in a compile-time assertion error; e.g.: /// /// ```compile_fail,E0080 /// use zerocopy::*; /// # use zerocopy_derive::*; /// /// #[derive(Immutable, KnownLayout)] /// #[repr(C)] /// struct ZSTy { /// leading_sized: u16, /// trailing_dst: [()], /// } /// /// let _ = Ref::<_, ZSTy>::from_bytes_with_elems(&b"UU"[..], 42); // ⚠ Compile Error! /// ``` #[inline] pub fn from_bytes_with_elems(source: B, count: usize) -> Result<Ref<B, T>, CastError<B, T>> { static_assert_dst_is_not_zst!(T); let expected_len = match T::size_for_metadata(count) { Some(len) => len, None => return Err(SizeError::new(source).into()), }; if source.len() != expected_len { return Err(SizeError::new(source).into()); } Self::from_bytes(source)Lines 1–500 of 1358. Load more
// SPDX-License-Identifier: (BSD-2-Clause OR Apache-2.0) OR MIT // // Copyright 2024 The Fuchsia Authors // // Licensed under the 2-Clause BSD License <LICENSE-BSD or // https://opensource.org/license/bsd-2-clause>, Apache License, Version 2.0 // <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option. // This file may not be copied, modified, or distributed except according to // those terms. use super::*; use crate::pointer::{ BecauseInvariantsEq, BecauseMutationCompatible, MutationCompatible, TransmuteFromPtr, }; mod def { use core::marker::PhantomData; use crate::{ ByteSlice, ByteSliceMut, CloneableByteSlice, CopyableByteSlice, IntoByteSlice, IntoByteSliceMut, }; /// A typed reference derived from a byte slice. /// /// A `Ref<B, T>` is a reference to a `T` which is stored in a byte slice, `B`. /// Unlike a native reference (`&T` or `&mut T`), `Ref<B, T>` has the same /// mutability as the byte slice it was constructed from (`B`). /// /// # Examples /// /// `Ref` can be used to treat a sequence of bytes as a structured type, and /// to read and write the fields of that type as if the byte slice reference /// were simply a reference to that type. /// /// ```rust /// use zerocopy::*; /// # use zerocopy_derive::*; /// /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)] /// #[repr(C)] /// struct UdpHeader { /// src_port: [u8; 2], /// dst_port: [u8; 2], /// length: [u8; 2], /// checksum: [u8; 2], /// } /// /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)] /// #[repr(C, packed)] /// struct UdpPacket { /// header: UdpHeader, /// body: [u8], /// } /// /// impl UdpPacket { /// pub fn parse<B: ByteSlice>(bytes: B) -> Option<Ref<B, UdpPacket>> { /// Ref::from_bytes(bytes).ok() /// } /// } /// ``` pub struct Ref<B, T: ?Sized>( // INVARIANTS: The referent (via `.deref`, `.deref_mut`, `.into`) byte // slice is aligned to `T`'s alignment and its size corresponds to a // valid size for `T`. B, PhantomData<T>, ); impl<B, T: ?Sized> Ref<B, T> { /// Constructs a new `Ref`. /// /// # Safety /// /// `bytes` dereferences (via [`deref`], [`deref_mut`], and [`into`]) to /// a byte slice which is aligned to `T`'s alignment and whose size is a /// valid size for `T`. /// /// [`deref`]: core::ops::Deref::deref /// [`deref_mut`]: core::ops::DerefMut::deref_mut /// [`into`]: core::convert::Into::into pub(crate) unsafe fn new_unchecked(bytes: B) -> Ref<B, T> { // INVARIANTS: The caller has promised that `bytes`'s referent is // validly-aligned and has a valid size. Ref(bytes, PhantomData) } } impl<B: ByteSlice, T: ?Sized> Ref<B, T> { /// Access the byte slice as a [`ByteSlice`]. /// /// # Safety /// /// The caller promises not to call methods on the returned /// [`ByteSlice`] other than `ByteSlice` methods (for example, via /// `Any::downcast_ref`). /// /// `as_byte_slice` promises to return a `ByteSlice` whose referent is /// validly-aligned for `T` and has a valid size for `T`. pub(crate) unsafe fn as_byte_slice(&self) -> &impl ByteSlice { // INVARIANTS: The caller promises not to call methods other than // those on `ByteSlice`. Since `B: ByteSlice`, dereference stability // guarantees that calling `ByteSlice` methods will not change the // address or length of `self.0`'s referent. // // SAFETY: By invariant on `self.0`, the alignment and size // post-conditions are upheld. &self.0 } } impl<B: ByteSliceMut, T: ?Sized> Ref<B, T> { /// Access the byte slice as a [`ByteSliceMut`]. /// /// # Safety /// /// The caller promises not to call methods on the returned /// [`ByteSliceMut`] other than `ByteSliceMut` methods (for example, via /// `Any::downcast_mut`). /// /// `as_byte_slice` promises to return a `ByteSlice` whose referent is /// validly-aligned for `T` and has a valid size for `T`. pub(crate) unsafe fn as_byte_slice_mut(&mut self) -> &mut impl ByteSliceMut { // INVARIANTS: The caller promises not to call methods other than // those on `ByteSliceMut`. Since `B: ByteSlice`, dereference // stability guarantees that calling `ByteSlice` methods will not // change the address or length of `self.0`'s referent. // // SAFETY: By invariant on `self.0`, the alignment and size // post-conditions are upheld. &mut self.0 } } impl<'a, B: IntoByteSlice<'a>, T: ?Sized> Ref<B, T> { /// Access the byte slice as an [`IntoByteSlice`]. /// /// # Safety /// /// The caller promises not to call methods on the returned /// [`IntoByteSlice`] other than `IntoByteSlice` methods (for example, /// via `Any::downcast_ref`). /// /// `as_byte_slice` promises to return a `ByteSlice` whose referent is /// validly-aligned for `T` and has a valid size for `T`. pub(crate) unsafe fn into_byte_slice(self) -> impl IntoByteSlice<'a> { // INVARIANTS: The caller promises not to call methods other than // those on `IntoByteSlice`. Since `B: ByteSlice`, dereference // stability guarantees that calling `ByteSlice` methods will not // change the address or length of `self.0`'s referent. // // SAFETY: By invariant on `self.0`, the alignment and size // post-conditions are upheld. self.0 } } impl<'a, B: IntoByteSliceMut<'a>, T: ?Sized> Ref<B, T> { /// Access the byte slice as an [`IntoByteSliceMut`]. /// /// # Safety /// /// The caller promises not to call methods on the returned /// [`IntoByteSliceMut`] other than `IntoByteSliceMut` methods (for /// example, via `Any::downcast_mut`). /// /// `as_byte_slice` promises to return a `ByteSlice` whose referent is /// validly-aligned for `T` and has a valid size for `T`. pub(crate) unsafe fn into_byte_slice_mut(self) -> impl IntoByteSliceMut<'a> { // INVARIANTS: The caller promises not to call methods other than // those on `IntoByteSliceMut`. Since `B: ByteSlice`, dereference // stability guarantees that calling `ByteSlice` methods will not // change the address or length of `self.0`'s referent. // // SAFETY: By invariant on `self.0`, the alignment and size // post-conditions are upheld. self.0 } } impl<B: CloneableByteSlice + Clone, T: ?Sized> Clone for Ref<B, T> { #[inline] fn clone(&self) -> Ref<B, T> { // INVARIANTS: Since `B: CloneableByteSlice`, `self.0.clone()` has // the same address and length as `self.0`. Since `self.0` upholds // the field invariants, so does `self.0.clone()`. Ref(self.0.clone(), PhantomData) } } // INVARIANTS: Since `B: CopyableByteSlice`, the copied `Ref`'s `.0` has the // same address and length as the original `Ref`'s `.0`. Since the original // upholds the field invariants, so does the copy. impl<B: CopyableByteSlice + Copy, T: ?Sized> Copy for Ref<B, T> {} } #[allow(unreachable_pub)] // This is a false positive on our MSRV toolchain. pub use def::Ref; use crate::pointer::{ invariant::{Aligned, BecauseExclusive, Initialized, Unaligned, Valid}, BecauseRead, PtrInner, }; impl<B, T> Ref<B, T> where B: ByteSlice, { #[must_use = "has no side effects"] pub(crate) fn sized_from(bytes: B) -> Result<Ref<B, T>, CastError<B, T>> { if bytes.len() != mem::size_of::<T>() { return Err(SizeError::new(bytes).into()); } if let Err(err) = util::validate_aligned_to::<_, T>(bytes.deref()) { return Err(err.with_src(bytes).into()); } // SAFETY: We just validated size and alignment. Ok(unsafe { Ref::new_unchecked(bytes) }) } } impl<B, T> Ref<B, T> where B: SplitByteSlice, { #[must_use = "has no side effects"] pub(crate) fn sized_from_prefix(bytes: B) -> Result<(Ref<B, T>, B), CastError<B, T>> { if bytes.len() < mem::size_of::<T>() { return Err(SizeError::new(bytes).into()); } if let Err(err) = util::validate_aligned_to::<_, T>(bytes.deref()) { return Err(err.with_src(bytes).into()); } let (bytes, suffix) = bytes.split_at(mem::size_of::<T>()).map_err( #[inline(always)] |b| SizeError::new(b).into(), )?; // SAFETY: We just validated alignment and that `bytes` is at least as // large as `T`. `bytes.split_at(mem::size_of::<T>())?` ensures that the // new `bytes` is exactly the size of `T`. By safety postcondition on // `SplitByteSlice::split_at` we can rely on `split_at` to produce the // correct `bytes` and `suffix`. let r = unsafe { Ref::new_unchecked(bytes) }; Ok((r, suffix)) } #[must_use = "has no side effects"] pub(crate) fn sized_from_suffix(bytes: B) -> Result<(B, Ref<B, T>), CastError<B, T>> { let bytes_len = bytes.len(); let split_at = if let Some(split_at) = bytes_len.checked_sub(mem::size_of::<T>()) { split_at } else { return Err(SizeError::new(bytes).into()); }; let (prefix, bytes) = bytes.split_at(split_at).map_err(|b| SizeError::new(b).into())?; if let Err(err) = util::validate_aligned_to::<_, T>(bytes.deref()) { return Err(err.with_src(bytes).into()); } // SAFETY: Since `split_at` is defined as `bytes_len - size_of::<T>()`, // the `bytes` which results from `let (prefix, bytes) = // bytes.split_at(split_at)?` has length `size_of::<T>()`. After // constructing `bytes`, we validate that it has the proper alignment. // By safety postcondition on `SplitByteSlice::split_at` we can rely on // `split_at` to produce the correct `prefix` and `bytes`. let r = unsafe { Ref::new_unchecked(bytes) }; Ok((prefix, r)) } } impl<B, T> Ref<B, T> where B: ByteSlice, T: KnownLayout + Immutable + ?Sized, { /// Constructs a `Ref` from a byte slice. /// /// If the length of `source` is not a [valid size of `T`][valid-size], or /// if `source` is not appropriately aligned for `T`, this returns `Err`. If /// [`T: Unaligned`][t-unaligned], you can [infallibly discard the alignment /// error][size-error-from]. /// /// `T` may be a sized type, a slice, or a [slice DST][slice-dst]. /// /// [valid-size]: crate::KnownLayout#what-is-a-valid-size /// [t-unaligned]: crate::Unaligned /// [size-error-from]: error/struct.SizeError.html#method.from-1 /// [slice-dst]: KnownLayout#dynamically-sized-types /// /// # Compile-Time Assertions /// /// This method cannot yet be used on unsized types whose dynamically-sized /// component is zero-sized. Attempting to use this method on such types /// results in a compile-time assertion error; e.g.: /// /// ```compile_fail,E0080 /// use zerocopy::*; /// # use zerocopy_derive::*; /// /// #[derive(Immutable, KnownLayout)] /// #[repr(C)] /// struct ZSTy { /// leading_sized: u16, /// trailing_dst: [()], /// } /// /// let _ = Ref::<_, ZSTy>::from_bytes(&b"UU"[..]); // ⚠ Compile Error! /// ``` #[must_use = "has no side effects"] #[inline] pub fn from_bytes(source: B) -> Result<Ref<B, T>, CastError<B, T>> { static_assert_dst_is_not_zst!(T); if let Err(e) = Ptr::from_ref(source.deref()).try_cast_into_no_leftover::<T, BecauseImmutable>(None) { return Err(e.with_src(()).with_src(source)); } // SAFETY: `try_cast_into_no_leftover` validates size and alignment. Ok(unsafe { Ref::new_unchecked(source) }) } } impl<B, T> Ref<B, T> where B: SplitByteSlice, T: KnownLayout + Immutable + ?Sized, { /// Constructs a `Ref` from the prefix of a byte slice. /// /// This method computes the [largest possible size of `T`][valid-size] that /// can fit in the leading bytes of `source`, then attempts to return both a /// `Ref` to those bytes, and a reference to the remaining bytes. If there /// are insufficient bytes, or if `source` is not appropriately aligned, /// this returns `Err`. If [`T: Unaligned`][t-unaligned], you can /// [infallibly discard the alignment error][size-error-from]. /// /// `T` may be a sized type, a slice, or a [slice DST][slice-dst]. /// /// [valid-size]: crate::KnownLayout#what-is-a-valid-size /// [t-unaligned]: crate::Unaligned /// [size-error-from]: error/struct.SizeError.html#method.from-1 /// [slice-dst]: KnownLayout#dynamically-sized-types /// /// # Compile-Time Assertions /// /// This method cannot yet be used on unsized types whose dynamically-sized /// component is zero-sized. Attempting to use this method on such types /// results in a compile-time assertion error; e.g.: /// /// ```compile_fail,E0080 /// use zerocopy::*; /// # use zerocopy_derive::*; /// /// #[derive(Immutable, KnownLayout)] /// #[repr(C)] /// struct ZSTy { /// leading_sized: u16, /// trailing_dst: [()], /// } /// /// let _ = Ref::<_, ZSTy>::from_prefix(&b"UU"[..]); // ⚠ Compile Error! /// ``` #[must_use = "has no side effects"] #[inline] pub fn from_prefix(source: B) -> Result<(Ref<B, T>, B), CastError<B, T>> { static_assert_dst_is_not_zst!(T); let remainder = match Ptr::from_ref(source.deref()) .try_cast_into::<T, BecauseImmutable>(CastType::Prefix, None) { Ok((_, remainder)) => remainder, Err(e) => { return Err(e.with_src(()).with_src(source)); } }; // SAFETY: `remainder` is constructed as a subset of `source`, and so it // cannot have a larger size than `source`. Both of their `len` methods // measure bytes (`source` deref's to `[u8]`, and `remainder` is a // `Ptr<[u8]>`), so `source.len() >= remainder.len()`. Thus, this cannot // underflow. #[allow(unstable_name_collisions)] let split_at = unsafe { source.len().unchecked_sub(remainder.len()) }; let (bytes, suffix) = source.split_at(split_at).map_err(|b| SizeError::new(b).into())?; // SAFETY: `try_cast_into` validates size and alignment, and returns a // `split_at` that indicates how many bytes of `source` correspond to a // valid `T`. By safety postcondition on `SplitByteSlice::split_at` we // can rely on `split_at` to produce the correct `source` and `suffix`. let r = unsafe { Ref::new_unchecked(bytes) }; Ok((r, suffix)) } /// Constructs a `Ref` from the suffix of a byte slice. /// /// This method computes the [largest possible size of `T`][valid-size] that /// can fit in the trailing bytes of `source`, then attempts to return both /// a `Ref` to those bytes, and a reference to the preceding bytes. If there /// are insufficient bytes, or if that suffix of `source` is not /// appropriately aligned, this returns `Err`. If [`T: /// Unaligned`][t-unaligned], you can [infallibly discard the alignment /// error][size-error-from]. /// /// `T` may be a sized type, a slice, or a [slice DST][slice-dst]. /// /// [valid-size]: crate::KnownLayout#what-is-a-valid-size /// [t-unaligned]: crate::Unaligned /// [size-error-from]: error/struct.SizeError.html#method.from-1 /// [slice-dst]: KnownLayout#dynamically-sized-types /// /// # Compile-Time Assertions /// /// This method cannot yet be used on unsized types whose dynamically-sized /// component is zero-sized. Attempting to use this method on such types /// results in a compile-time assertion error; e.g.: /// /// ```compile_fail,E0080 /// use zerocopy::*; /// # use zerocopy_derive::*; /// /// #[derive(Immutable, KnownLayout)] /// #[repr(C)] /// struct ZSTy { /// leading_sized: u16, /// trailing_dst: [()], /// } /// /// let _ = Ref::<_, ZSTy>::from_suffix(&b"UU"[..]); // ⚠ Compile Error! /// ``` #[must_use = "has no side effects"] #[inline] pub fn from_suffix(source: B) -> Result<(B, Ref<B, T>), CastError<B, T>> { static_assert_dst_is_not_zst!(T); let remainder = match Ptr::from_ref(source.deref()) .try_cast_into::<T, BecauseImmutable>(CastType::Suffix, None) { Ok((_, remainder)) => remainder, Err(e) => { let e = e.with_src(()); return Err(e.with_src(source)); } }; let split_at = remainder.len(); let (prefix, bytes) = source.split_at(split_at).map_err(|b| SizeError::new(b).into())?; // SAFETY: `try_cast_into` validates size and alignment, and returns a // `split_at` that indicates how many bytes of `source` correspond to a // valid `T`. By safety postcondition on `SplitByteSlice::split_at` we // can rely on `split_at` to produce the correct `prefix` and `bytes`. let r = unsafe { Ref::new_unchecked(bytes) }; Ok((prefix, r)) } } impl<B, T> Ref<B, T> where B: ByteSlice, T: KnownLayout<PointerMetadata = usize> + Immutable + ?Sized, { /// Constructs a `Ref` from the given bytes with DST length equal to `count` /// without copying. /// /// This method attempts to return a `Ref` to the prefix of `source` /// interpreted as a `T` with `count` trailing elements, and a reference to /// the remaining bytes. If the length of `source` is not equal to the size /// of `Self` with `count` elements, or if `source` is not appropriately /// aligned, this returns `Err`. If [`T: Unaligned`][t-unaligned], you can /// [infallibly discard the alignment error][size-error-from]. /// /// [t-unaligned]: crate::Unaligned /// [size-error-from]: error/struct.SizeError.html#method.from-1 /// /// # Compile-Time Assertions /// /// This method cannot yet be used on unsized types whose dynamically-sized /// component is zero-sized. Attempting to use this method on such types /// results in a compile-time assertion error; e.g.: /// /// ```compile_fail,E0080 /// use zerocopy::*; /// # use zerocopy_derive::*; /// /// #[derive(Immutable, KnownLayout)] /// #[repr(C)] /// struct ZSTy { /// leading_sized: u16, /// trailing_dst: [()], /// } /// /// let _ = Ref::<_, ZSTy>::from_bytes_with_elems(&b"UU"[..], 42); // ⚠ Compile Error! /// ``` #[inline] pub fn from_bytes_with_elems(source: B, count: usize) -> Result<Ref<B, T>, CastError<B, T>> { static_assert_dst_is_not_zst!(T); let expected_len = match T::size_for_metadata(count) { Some(len) => len, None => return Err(SizeError::new(source).into()), }; if source.len() != expected_len { return Err(SizeError::new(source).into()); } Self::from_bytes(source)