// SPDX-License-Identifier: (BSD-2-Clause OR Apache-2.0) OR MIT//// Copyright 2025 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::invariant::{Aligned, Exclusive, Invariants, Shared, Valid}; /// Types that can be split in two.////// This trait generalizes Rust's existing support for splitting slices to/// support slices and slice-based dynamically-sized types ("slice DSTs").////// # Implementation////// **Do not implement this trait yourself!** Instead, use/// [`#[derive(SplitAt)]`][derive]; e.g.:////// ```/// # use zerocopy_derive::{SplitAt, KnownLayout};/// #[derive(SplitAt, KnownLayout)]/// #[repr(C)]/// struct MyStruct<T: ?Sized> {/// # /*/// ...,/// # *//// // `SplitAt` types must have at least one field./// field: T,/// }/// ```////// This derive performs a sophisticated, compile-time safety analysis to/// determine whether a type is `SplitAt`.////// # Safety////// This trait does not convey any safety guarantees to code outside this crate.////// You must not rely on the `#[doc(hidden)]` internals of `SplitAt`. Future/// releases of zerocopy may make backwards-breaking changes to these items,/// including changes that only affect soundness, which may cause code which/// uses those items to silently become unsound.///#[cfg_attr(feature = "derive", doc = "[derive]: zerocopy_derive::SplitAt")]#[cfg_attr( not(feature = "derive"), doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.SplitAt.html"),)]#[cfg_attr( not(no_zerocopy_diagnostic_on_unimplemented_1_78_0), diagnostic::on_unimplemented(note = "Consider adding `#[derive(SplitAt)]` to `{Self}`"))]// # Safety//// The trailing slice is well-aligned for its element type. `Self` is `[T]`, or// a `repr(C)` or `repr(transparent)` slice DST.pub unsafe trait SplitAt: KnownLayout<PointerMetadata = usize> { /// The element type of the trailing slice. type Elem; #[doc(hidden)] fn only_derive_is_allowed_to_implement_this_trait() where Self: Sized; /// Unsafely splits `self` in two. /// /// # Safety /// /// The caller promises that `l_len` is not greater than the length of /// `self`'s trailing slice. /// #[doc = codegen_section!( header = "h5", bench = "split_at_unchecked", format = "coco", arity = 2, [ open @index 1 @title "Unsized" @variant "dynamic_size" ], [ @index 2 @title "Dynamically Padded" @variant "dynamic_padding" ] )] #[inline] #[must_use] unsafe fn split_at_unchecked(&self, l_len: usize) -> Split<&Self> { // SAFETY: By precondition on the caller, `l_len <= self.len()`. unsafe { Split::<&Self>::new(self, l_len) } } /// Attempts to split `self` in two. /// /// Returns `None` if `l_len` is greater than the length of `self`'s /// trailing slice. /// /// # Examples /// /// ``` /// use zerocopy::{SplitAt, FromBytes}; /// # use zerocopy_derive::*; /// /// #[derive(SplitAt, FromBytes, KnownLayout, Immutable)] /// #[repr(C)] /// struct Packet { /// length: u8, /// body: [u8], /// } /// /// // These bytes encode a `Packet`. /// let bytes = &[4, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; /// /// let packet = Packet::ref_from_bytes(bytes).unwrap(); /// /// assert_eq!(packet.length, 4); /// assert_eq!(packet.body, [1, 2, 3, 4, 5, 6, 7, 8, 9]); /// /// // Attempt to split `packet` at `length`. /// let split = packet.split_at(packet.length as usize).unwrap(); /// /// // Use the `Immutable` bound on `Packet` to prove that it's okay to /// // return concurrent references to `packet` and `rest`. /// let (packet, rest) = split.via_immutable(); /// /// assert_eq!(packet.length, 4); /// assert_eq!(packet.body, [1, 2, 3, 4]); /// assert_eq!(rest, [5, 6, 7, 8, 9]); /// ``` /// #[doc = codegen_section!( header = "h5", bench = "split_at", format = "coco", arity = 2, [ open @index 1 @title "Unsized" @variant "dynamic_size" ], [ @index 2 @title "Dynamically Padded" @variant "dynamic_padding" ] )] #[inline] #[must_use = "has no side effects"] fn split_at(&self, l_len: usize) -> Option<Split<&Self>> { MetadataOf::new_in_bounds(self, l_len).map( #[inline(always)] |l_len| { // SAFETY: We have ensured that `l_len <= self.len()` (by // post-condition on `MetadataOf::new_in_bounds`) unsafe { Split::new(self, l_len.get()) } }, ) } /// Unsafely splits `self` in two. /// /// # Safety /// /// The caller promises that `l_len` is not greater than the length of /// `self`'s trailing slice. /// #[doc = codegen_header!("h5", "split_at_mut_unchecked")] /// /// See [`SplitAt::split_at_unchecked`](#method.split_at_unchecked.codegen). #[inline] #[must_use] unsafe fn split_at_mut_unchecked(&mut self, l_len: usize) -> Split<&mut Self> { // SAFETY: By precondition on the caller, `l_len <= self.len()`. unsafe { Split::<&mut Self>::new(self, l_len) } } /// Attempts to split `self` in two. /// /// Returns `None` if `l_len` is greater than the length of `self`'s /// trailing slice, or if the given `l_len` would result in [the trailing /// padding](KnownLayout#slice-dst-layout) of the left portion overlapping /// the right portion. /// /// /// # Examples /// /// ``` /// use zerocopy::{SplitAt, FromBytes}; /// # use zerocopy_derive::*; /// /// #[derive(SplitAt, FromBytes, KnownLayout, IntoBytes)] /// #[repr(C)] /// struct Packet<B: ?Sized> { /// length: u8, /// body: B, /// } /// /// // These bytes encode a `Packet`. /// let mut bytes = &mut [4, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; /// /// let packet = Packet::<[u8]>::mut_from_bytes(bytes).unwrap(); /// /// assert_eq!(packet.length, 4); /// assert_eq!(packet.body, [1, 2, 3, 4, 5, 6, 7, 8, 9]); /// /// { /// // Attempt to split `packet` at `length`. /// let split = packet.split_at_mut(packet.length as usize).unwrap(); /// /// // Use the `IntoBytes` bound on `Packet` to prove that it's okay to /// // return concurrent references to `packet` and `rest`. /// let (packet, rest) = split.via_into_bytes(); /// /// assert_eq!(packet.length, 4); /// assert_eq!(packet.body, [1, 2, 3, 4]); /// assert_eq!(rest, [5, 6, 7, 8, 9]); /// /// rest.fill(0); /// } /// /// assert_eq!(packet.length, 4); /// assert_eq!(packet.body, [1, 2, 3, 4, 0, 0, 0, 0, 0]); /// ``` /// #[doc = codegen_header!("h5", "split_at_mut")] /// /// See [`SplitAt::split_at`](#method.split_at.codegen). #[inline] fn split_at_mut(&mut self, l_len: usize) -> Option<Split<&mut Self>> { MetadataOf::new_in_bounds(self, l_len).map( #[inline(always)] |l_len| { // SAFETY: We have ensured that `l_len <= self.len()` (by // post-condition on `MetadataOf::new_in_bounds`) unsafe { Split::new(self, l_len.get()) } }, ) }} // SAFETY: `[T]`'s trailing slice is `[T]`, which is trivially aligned.unsafe impl<T> SplitAt for [T] { type Elem = T; #[inline] #[allow(dead_code)] fn only_derive_is_allowed_to_implement_this_trait() where Self: Sized, { }} /// A `T` that has been split into two possibly-overlapping parts.////// For some dynamically sized types, the padding that appears after the/// trailing slice field [is a dynamic function of the trailing slice/// length](KnownLayout#slice-dst-layout). If `T` is split at a length that/// requires trailing padding, the trailing padding of the left part of the/// split `T` will overlap the right part. If `T` is a mutable reference or/// permits interior mutation, you must ensure that the left and right parts do/// not overlap. You can do this at zero-cost using using/// [`Self::via_immutable`], [`Self::via_into_bytes`], or/// [`Self::via_unaligned`], or with a dynamic check by using/// [`Self::via_runtime_check`].#[derive(Debug)]pub struct Split<T> { /// A pointer to the source slice DST. source: T, /// The length of the future left half of `source`. /// /// # Safety /// /// If `source` is a pointer to a slice DST, `l_len` is no greater than /// `source`'s length. l_len: usize,} impl<T> Split<T> { /// Produces a `Split` of `source` with `l_len`. /// /// # Safety /// /// `l_len` is no greater than `source`'s length. #[inline(always)] unsafe fn new(source: T, l_len: usize) -> Self { Self { source, l_len } }} impl<'a, T> Split<&'a T>where T: ?Sized + SplitAt,{ #[inline(always)] fn into_ptr(self) -> Split<Ptr<'a, T, (Shared, Aligned, Valid)>> { let source = Ptr::from_ref(self.source); // SAFETY: `Ptr::from_ref(self.source)` points to exactly `self.source` // and thus maintains the invariants of `self` with respect to `l_len`. unsafe { Split::new(source, self.l_len) } } /// Produces the split parts of `self`, using [`Immutable`] to ensure that /// it is sound to have concurrent references to both parts. /// /// # Examples /// /// ``` /// use zerocopy::{SplitAt, FromBytes}; /// # use zerocopy_derive::*; /// /// #[derive(SplitAt, FromBytes, KnownLayout, Immutable)] /// #[repr(C)] /// struct Packet { /// length: u8, /// body: [u8], /// } /// /// // These bytes encode a `Packet`. /// let bytes = &[4, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; /// /// let packet = Packet::ref_from_bytes(bytes).unwrap(); /// /// assert_eq!(packet.length, 4); /// assert_eq!(packet.body, [1, 2, 3, 4, 5, 6, 7, 8, 9]); /// /// // Attempt to split `packet` at `length`. /// let split = packet.split_at(packet.length as usize).unwrap(); /// /// // Use the `Immutable` bound on `Packet` to prove that it's okay to /// // return concurrent references to `packet` and `rest`. /// let (packet, rest) = split.via_immutable(); /// /// assert_eq!(packet.length, 4); /// assert_eq!(packet.body, [1, 2, 3, 4]); /// assert_eq!(rest, [5, 6, 7, 8, 9]); /// ``` /// #[doc = codegen_section!( header = "h5", bench = "split_via_immutable", format = "coco", arity = 2, [ open @index 1 @title "Unsized" @variant "dynamic_size" ], [ @index 2 @title "Dynamically Padded" @variant "dynamic_padding" ] )] #[must_use = "has no side effects"] #[inline(always)] pub fn via_immutable(self) -> (&'a T, &'a [T::Elem]) where T: Immutable, { let (l, r) = self.into_ptr().via_immutable(); (l.as_ref(), r.as_ref()) } /// Produces the split parts of `self`, using [`IntoBytes`] to ensure that /// it is sound to have concurrent references to both parts. /// /// # Examples /// /// ``` /// use zerocopy::{SplitAt, FromBytes}; /// # use zerocopy_derive::*; /// /// #[derive(SplitAt, FromBytes, KnownLayout, Immutable, IntoBytes)] /// #[repr(C)] /// struct Packet<B: ?Sized> { /// length: u8, /// body: B, /// } /// /// // These bytes encode a `Packet`. /// let bytes = &[4, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; /// /// let packet = Packet::<[u8]>::ref_from_bytes(bytes).unwrap(); /// /// assert_eq!(packet.length, 4); /// assert_eq!(packet.body, [1, 2, 3, 4, 5, 6, 7, 8, 9]); /// /// // Attempt to split `packet` at `length`. /// let split = packet.split_at(packet.length as usize).unwrap(); /// /// // Use the `IntoBytes` bound on `Packet` to prove that it's okay to /// // return concurrent references to `packet` and `rest`. /// let (packet, rest) = split.via_into_bytes(); /// /// assert_eq!(packet.length, 4); /// assert_eq!(packet.body, [1, 2, 3, 4]); /// assert_eq!(rest, [5, 6, 7, 8, 9]); /// ``` /// #[doc = codegen_header!("h5", "split_via_into_bytes")] /// /// See [`Split::via_immutable`](#method.split_via_immutable.codegen). #[must_use = "has no side effects"] #[inline(always)] pub fn via_into_bytes(self) -> (&'a T, &'a [T::Elem]) where T: IntoBytes, { let (l, r) = self.into_ptr().via_into_bytes(); (l.as_ref(), r.as_ref()) } /// Produces the split parts of `self`, using [`Unaligned`] to ensure that /// it is sound to have concurrent references to both parts. /// /// # Examples /// /// ``` /// use zerocopy::{SplitAt, FromBytes}; /// # use zerocopy_derive::*; /// /// #[derive(SplitAt, FromBytes, KnownLayout, Immutable, Unaligned)] /// #[repr(C)] /// struct Packet { /// length: u8, /// body: [u8], /// } /// /// // These bytes encode a `Packet`. /// let bytes = &[4, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; /// /// let packet = Packet::ref_from_bytes(bytes).unwrap(); /// /// assert_eq!(packet.length, 4); /// assert_eq!(packet.body, [1, 2, 3, 4, 5, 6, 7, 8, 9]); /// /// // Attempt to split `packet` at `length`. /// let split = packet.split_at(packet.length as usize).unwrap(); /// /// // Use the `Unaligned` bound on `Packet` to prove that it's okay to /// // return concurrent references to `packet` and `rest`. /// let (packet, rest) = split.via_unaligned(); /// /// assert_eq!(packet.length, 4); /// assert_eq!(packet.body, [1, 2, 3, 4]); /// assert_eq!(rest, [5, 6, 7, 8, 9]); /// ``` /// #[doc = codegen_header!("h5", "split_via_unaligned")] /// /// See [`Split::via_immutable`](#method.split_via_immutable.codegen). #[must_use = "has no side effects"] #[inline(always)] pub fn via_unaligned(self) -> (&'a T, &'a [T::Elem]) where T: Unaligned, { let (l, r) = self.into_ptr().via_unaligned(); (l.as_ref(), r.as_ref()) } /// Produces the split parts of `self`, using a dynamic check to ensure that /// it is sound to have concurrent references to both parts. You should /// prefer using [`Self::via_immutable`], [`Self::via_into_bytes`], or /// [`Self::via_unaligned`], which have no runtime cost. /// /// Note that this check is overly conservative if `T` is [`Immutable`]; for /// some types, this check will reject some splits which /// [`Self::via_immutable`] will accept. /// /// # Examples /// /// ``` /// use zerocopy::{SplitAt, FromBytes, IntoBytes, network_endian::U16}; /// # use zerocopy_derive::*; /// /// #[derive(SplitAt, FromBytes, KnownLayout, Immutable, Debug)] /// #[repr(C, align(2))] /// struct Packet { /// length: U16, /// body: [u8], /// } /// /// // These bytes encode a `Packet`. /// let bytes = [ /// 4u16.to_be(), /// 1u16.to_be(),Lines 1–500 of 1090. Load more
// SPDX-License-Identifier: (BSD-2-Clause OR Apache-2.0) OR MIT // // Copyright 2025 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::invariant::{Aligned, Exclusive, Invariants, Shared, Valid}; /// Types that can be split in two. /// /// This trait generalizes Rust's existing support for splitting slices to /// support slices and slice-based dynamically-sized types ("slice DSTs"). /// /// # Implementation /// /// **Do not implement this trait yourself!** Instead, use /// [`#[derive(SplitAt)]`][derive]; e.g.: /// /// ``` /// # use zerocopy_derive::{SplitAt, KnownLayout}; /// #[derive(SplitAt, KnownLayout)] /// #[repr(C)] /// struct MyStruct<T: ?Sized> { /// # /* /// ..., /// # */ /// // `SplitAt` types must have at least one field. /// field: T, /// } /// ``` /// /// This derive performs a sophisticated, compile-time safety analysis to /// determine whether a type is `SplitAt`. /// /// # Safety /// /// This trait does not convey any safety guarantees to code outside this crate. /// /// You must not rely on the `#[doc(hidden)]` internals of `SplitAt`. Future /// releases of zerocopy may make backwards-breaking changes to these items, /// including changes that only affect soundness, which may cause code which /// uses those items to silently become unsound. /// #[cfg_attr(feature = "derive", doc = "[derive]: zerocopy_derive::SplitAt")] #[cfg_attr( not(feature = "derive"), doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.SplitAt.html"), )] #[cfg_attr( not(no_zerocopy_diagnostic_on_unimplemented_1_78_0), diagnostic::on_unimplemented(note = "Consider adding `#[derive(SplitAt)]` to `{Self}`") )] // # Safety // // The trailing slice is well-aligned for its element type. `Self` is `[T]`, or // a `repr(C)` or `repr(transparent)` slice DST. pub unsafe trait SplitAt: KnownLayout<PointerMetadata = usize> { /// The element type of the trailing slice. type Elem; #[doc(hidden)] fn only_derive_is_allowed_to_implement_this_trait() where Self: Sized; /// Unsafely splits `self` in two. /// /// # Safety /// /// The caller promises that `l_len` is not greater than the length of /// `self`'s trailing slice. /// #[doc = codegen_section!( header = "h5", bench = "split_at_unchecked", format = "coco", arity = 2, [ open @index 1 @title "Unsized" @variant "dynamic_size" ], [ @index 2 @title "Dynamically Padded" @variant "dynamic_padding" ] )] #[inline] #[must_use] unsafe fn split_at_unchecked(&self, l_len: usize) -> Split<&Self> { // SAFETY: By precondition on the caller, `l_len <= self.len()`. unsafe { Split::<&Self>::new(self, l_len) } } /// Attempts to split `self` in two. /// /// Returns `None` if `l_len` is greater than the length of `self`'s /// trailing slice. /// /// # Examples /// /// ``` /// use zerocopy::{SplitAt, FromBytes}; /// # use zerocopy_derive::*; /// /// #[derive(SplitAt, FromBytes, KnownLayout, Immutable)] /// #[repr(C)] /// struct Packet { /// length: u8, /// body: [u8], /// } /// /// // These bytes encode a `Packet`. /// let bytes = &[4, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; /// /// let packet = Packet::ref_from_bytes(bytes).unwrap(); /// /// assert_eq!(packet.length, 4); /// assert_eq!(packet.body, [1, 2, 3, 4, 5, 6, 7, 8, 9]); /// /// // Attempt to split `packet` at `length`. /// let split = packet.split_at(packet.length as usize).unwrap(); /// /// // Use the `Immutable` bound on `Packet` to prove that it's okay to /// // return concurrent references to `packet` and `rest`. /// let (packet, rest) = split.via_immutable(); /// /// assert_eq!(packet.length, 4); /// assert_eq!(packet.body, [1, 2, 3, 4]); /// assert_eq!(rest, [5, 6, 7, 8, 9]); /// ``` /// #[doc = codegen_section!( header = "h5", bench = "split_at", format = "coco", arity = 2, [ open @index 1 @title "Unsized" @variant "dynamic_size" ], [ @index 2 @title "Dynamically Padded" @variant "dynamic_padding" ] )] #[inline] #[must_use = "has no side effects"] fn split_at(&self, l_len: usize) -> Option<Split<&Self>> { MetadataOf::new_in_bounds(self, l_len).map( #[inline(always)] |l_len| { // SAFETY: We have ensured that `l_len <= self.len()` (by // post-condition on `MetadataOf::new_in_bounds`) unsafe { Split::new(self, l_len.get()) } }, ) } /// Unsafely splits `self` in two. /// /// # Safety /// /// The caller promises that `l_len` is not greater than the length of /// `self`'s trailing slice. /// #[doc = codegen_header!("h5", "split_at_mut_unchecked")] /// /// See [`SplitAt::split_at_unchecked`](#method.split_at_unchecked.codegen). #[inline] #[must_use] unsafe fn split_at_mut_unchecked(&mut self, l_len: usize) -> Split<&mut Self> { // SAFETY: By precondition on the caller, `l_len <= self.len()`. unsafe { Split::<&mut Self>::new(self, l_len) } } /// Attempts to split `self` in two. /// /// Returns `None` if `l_len` is greater than the length of `self`'s /// trailing slice, or if the given `l_len` would result in [the trailing /// padding](KnownLayout#slice-dst-layout) of the left portion overlapping /// the right portion. /// /// /// # Examples /// /// ``` /// use zerocopy::{SplitAt, FromBytes}; /// # use zerocopy_derive::*; /// /// #[derive(SplitAt, FromBytes, KnownLayout, IntoBytes)] /// #[repr(C)] /// struct Packet<B: ?Sized> { /// length: u8, /// body: B, /// } /// /// // These bytes encode a `Packet`. /// let mut bytes = &mut [4, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; /// /// let packet = Packet::<[u8]>::mut_from_bytes(bytes).unwrap(); /// /// assert_eq!(packet.length, 4); /// assert_eq!(packet.body, [1, 2, 3, 4, 5, 6, 7, 8, 9]); /// /// { /// // Attempt to split `packet` at `length`. /// let split = packet.split_at_mut(packet.length as usize).unwrap(); /// /// // Use the `IntoBytes` bound on `Packet` to prove that it's okay to /// // return concurrent references to `packet` and `rest`. /// let (packet, rest) = split.via_into_bytes(); /// /// assert_eq!(packet.length, 4); /// assert_eq!(packet.body, [1, 2, 3, 4]); /// assert_eq!(rest, [5, 6, 7, 8, 9]); /// /// rest.fill(0); /// } /// /// assert_eq!(packet.length, 4); /// assert_eq!(packet.body, [1, 2, 3, 4, 0, 0, 0, 0, 0]); /// ``` /// #[doc = codegen_header!("h5", "split_at_mut")] /// /// See [`SplitAt::split_at`](#method.split_at.codegen). #[inline] fn split_at_mut(&mut self, l_len: usize) -> Option<Split<&mut Self>> { MetadataOf::new_in_bounds(self, l_len).map( #[inline(always)] |l_len| { // SAFETY: We have ensured that `l_len <= self.len()` (by // post-condition on `MetadataOf::new_in_bounds`) unsafe { Split::new(self, l_len.get()) } }, ) } } // SAFETY: `[T]`'s trailing slice is `[T]`, which is trivially aligned. unsafe impl<T> SplitAt for [T] { type Elem = T; #[inline] #[allow(dead_code)] fn only_derive_is_allowed_to_implement_this_trait() where Self: Sized, { } } /// A `T` that has been split into two possibly-overlapping parts. /// /// For some dynamically sized types, the padding that appears after the /// trailing slice field [is a dynamic function of the trailing slice /// length](KnownLayout#slice-dst-layout). If `T` is split at a length that /// requires trailing padding, the trailing padding of the left part of the /// split `T` will overlap the right part. If `T` is a mutable reference or /// permits interior mutation, you must ensure that the left and right parts do /// not overlap. You can do this at zero-cost using using /// [`Self::via_immutable`], [`Self::via_into_bytes`], or /// [`Self::via_unaligned`], or with a dynamic check by using /// [`Self::via_runtime_check`]. #[derive(Debug)] pub struct Split<T> { /// A pointer to the source slice DST. source: T, /// The length of the future left half of `source`. /// /// # Safety /// /// If `source` is a pointer to a slice DST, `l_len` is no greater than /// `source`'s length. l_len: usize, } impl<T> Split<T> { /// Produces a `Split` of `source` with `l_len`. /// /// # Safety /// /// `l_len` is no greater than `source`'s length. #[inline(always)] unsafe fn new(source: T, l_len: usize) -> Self { Self { source, l_len } } } impl<'a, T> Split<&'a T> where T: ?Sized + SplitAt, { #[inline(always)] fn into_ptr(self) -> Split<Ptr<'a, T, (Shared, Aligned, Valid)>> { let source = Ptr::from_ref(self.source); // SAFETY: `Ptr::from_ref(self.source)` points to exactly `self.source` // and thus maintains the invariants of `self` with respect to `l_len`. unsafe { Split::new(source, self.l_len) } } /// Produces the split parts of `self`, using [`Immutable`] to ensure that /// it is sound to have concurrent references to both parts. /// /// # Examples /// /// ``` /// use zerocopy::{SplitAt, FromBytes}; /// # use zerocopy_derive::*; /// /// #[derive(SplitAt, FromBytes, KnownLayout, Immutable)] /// #[repr(C)] /// struct Packet { /// length: u8, /// body: [u8], /// } /// /// // These bytes encode a `Packet`. /// let bytes = &[4, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; /// /// let packet = Packet::ref_from_bytes(bytes).unwrap(); /// /// assert_eq!(packet.length, 4); /// assert_eq!(packet.body, [1, 2, 3, 4, 5, 6, 7, 8, 9]); /// /// // Attempt to split `packet` at `length`. /// let split = packet.split_at(packet.length as usize).unwrap(); /// /// // Use the `Immutable` bound on `Packet` to prove that it's okay to /// // return concurrent references to `packet` and `rest`. /// let (packet, rest) = split.via_immutable(); /// /// assert_eq!(packet.length, 4); /// assert_eq!(packet.body, [1, 2, 3, 4]); /// assert_eq!(rest, [5, 6, 7, 8, 9]); /// ``` /// #[doc = codegen_section!( header = "h5", bench = "split_via_immutable", format = "coco", arity = 2, [ open @index 1 @title "Unsized" @variant "dynamic_size" ], [ @index 2 @title "Dynamically Padded" @variant "dynamic_padding" ] )] #[must_use = "has no side effects"] #[inline(always)] pub fn via_immutable(self) -> (&'a T, &'a [T::Elem]) where T: Immutable, { let (l, r) = self.into_ptr().via_immutable(); (l.as_ref(), r.as_ref()) } /// Produces the split parts of `self`, using [`IntoBytes`] to ensure that /// it is sound to have concurrent references to both parts. /// /// # Examples /// /// ``` /// use zerocopy::{SplitAt, FromBytes}; /// # use zerocopy_derive::*; /// /// #[derive(SplitAt, FromBytes, KnownLayout, Immutable, IntoBytes)] /// #[repr(C)] /// struct Packet<B: ?Sized> { /// length: u8, /// body: B, /// } /// /// // These bytes encode a `Packet`. /// let bytes = &[4, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; /// /// let packet = Packet::<[u8]>::ref_from_bytes(bytes).unwrap(); /// /// assert_eq!(packet.length, 4); /// assert_eq!(packet.body, [1, 2, 3, 4, 5, 6, 7, 8, 9]); /// /// // Attempt to split `packet` at `length`. /// let split = packet.split_at(packet.length as usize).unwrap(); /// /// // Use the `IntoBytes` bound on `Packet` to prove that it's okay to /// // return concurrent references to `packet` and `rest`. /// let (packet, rest) = split.via_into_bytes(); /// /// assert_eq!(packet.length, 4); /// assert_eq!(packet.body, [1, 2, 3, 4]); /// assert_eq!(rest, [5, 6, 7, 8, 9]); /// ``` /// #[doc = codegen_header!("h5", "split_via_into_bytes")] /// /// See [`Split::via_immutable`](#method.split_via_immutable.codegen). #[must_use = "has no side effects"] #[inline(always)] pub fn via_into_bytes(self) -> (&'a T, &'a [T::Elem]) where T: IntoBytes, { let (l, r) = self.into_ptr().via_into_bytes(); (l.as_ref(), r.as_ref()) } /// Produces the split parts of `self`, using [`Unaligned`] to ensure that /// it is sound to have concurrent references to both parts. /// /// # Examples /// /// ``` /// use zerocopy::{SplitAt, FromBytes}; /// # use zerocopy_derive::*; /// /// #[derive(SplitAt, FromBytes, KnownLayout, Immutable, Unaligned)] /// #[repr(C)] /// struct Packet { /// length: u8, /// body: [u8], /// } /// /// // These bytes encode a `Packet`. /// let bytes = &[4, 1, 2, 3, 4, 5, 6, 7, 8, 9][..]; /// /// let packet = Packet::ref_from_bytes(bytes).unwrap(); /// /// assert_eq!(packet.length, 4); /// assert_eq!(packet.body, [1, 2, 3, 4, 5, 6, 7, 8, 9]); /// /// // Attempt to split `packet` at `length`. /// let split = packet.split_at(packet.length as usize).unwrap(); /// /// // Use the `Unaligned` bound on `Packet` to prove that it's okay to /// // return concurrent references to `packet` and `rest`. /// let (packet, rest) = split.via_unaligned(); /// /// assert_eq!(packet.length, 4); /// assert_eq!(packet.body, [1, 2, 3, 4]); /// assert_eq!(rest, [5, 6, 7, 8, 9]); /// ``` /// #[doc = codegen_header!("h5", "split_via_unaligned")] /// /// See [`Split::via_immutable`](#method.split_via_immutable.codegen). #[must_use = "has no side effects"] #[inline(always)] pub fn via_unaligned(self) -> (&'a T, &'a [T::Elem]) where T: Unaligned, { let (l, r) = self.into_ptr().via_unaligned(); (l.as_ref(), r.as_ref()) } /// Produces the split parts of `self`, using a dynamic check to ensure that /// it is sound to have concurrent references to both parts. You should /// prefer using [`Self::via_immutable`], [`Self::via_into_bytes`], or /// [`Self::via_unaligned`], which have no runtime cost. /// /// Note that this check is overly conservative if `T` is [`Immutable`]; for /// some types, this check will reject some splits which /// [`Self::via_immutable`] will accept. /// /// # Examples /// /// ``` /// use zerocopy::{SplitAt, FromBytes, IntoBytes, network_endian::U16}; /// # use zerocopy_derive::*; /// /// #[derive(SplitAt, FromBytes, KnownLayout, Immutable, Debug)] /// #[repr(C, align(2))] /// struct Packet { /// length: U16, /// body: [u8], /// } /// /// // These bytes encode a `Packet`. /// let bytes = [ /// 4u16.to_be(), /// 1u16.to_be(),