Something went wrong. Try again.
(I'm so sorry!) Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899// 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::{ BecauseMutationCompatible, BecauseSharedCompatible, MutationCompatible, TransmuteFromPtr,};
mod def { use core::marker::PhantomData;
use crate::{ ByteSlice, ByteSliceMut, CloneableByteSlice, CopyableByteSlice, IntoByteSlice, IntoByteSliceMut, KnownLayout, PointerMetadata, };
/// 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 is valid for `T`. // - If `T: KnownLayout`, let `metadata` be // `T::PointerMetadata::from_elem_count` applied to `elem_count`. // Then `T::size_for_metadata(metadata)` is `Some(referent.len())`. bytes: B, // Ignored when `T` does not implement `KnownLayout`. elem_count: usize, _marker: PhantomData<T>, }
impl<B, T> Ref<B, T> { /// Constructs a new `Ref` to a sized `T`. /// /// # Safety /// /// `bytes` dereferences (via [`deref`], [`deref_mut`], and [`into`]) to /// a byte slice which is aligned to `T`'s alignment and whose size is /// `size_of::<T>()`. /// /// [`deref`]: core::ops::Deref::deref /// [`deref_mut`]: core::ops::DerefMut::deref_mut /// [`into`]: core::convert::Into::into pub(super) unsafe fn new_sized_unchecked(bytes: B) -> Ref<B, T> { // INVARIANTS: The caller has promised that `bytes`'s referent is // validly aligned and has size `size_of::<T>()`. If `T: // KnownLayout`, then, since `T` is sized, `T::PointerMetadata` is // `()`. `from_elem_count` returns `()` for any element count, and // `T::size_for_metadata(()) == Some(size_of::<T>())`. `size_of` // reports this size in bytes [1]. // // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of.html: // // Returns the size of a type in bytes. Ref { bytes, elem_count: 0, _marker: PhantomData } } }
impl<B, T: KnownLayout + ?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 satisfies /// `T::size_for_metadata(metadata) == Some(referent.len())`. /// /// [`deref`]: core::ops::Deref::deref /// [`deref_mut`]: core::ops::DerefMut::deref_mut /// [`into`]: core::convert::Into::into pub(super) unsafe fn new_unchecked(bytes: B, metadata: T::PointerMetadata) -> Ref<B, T> { // INVARIANTS: The caller has promised that `bytes`'s referent is // validly aligned and has exactly the size described by `metadata`. // `KnownLayout::PointerMetadata` is `()` for sized types and // `usize` for slice DSTs. For both permitted metadata types, // `from_elem_count(metadata.to_elem_count()) == metadata`: `()` // round-trips through zero, while `usize` round-trips through // itself. Thus, storing the element count preserves the metadata // whose size the caller validated. This agrees with Rust's // language-level definition of slice pointer metadata [1]. // // [1] Per https://doc.rust-lang.org/1.56.0/reference/dynamically-sized-types.html: // // Pointers to slices also store the number of elements of the // slice. Ref { bytes, elem_count: metadata.to_elem_count(), _marker: PhantomData } }
/// Gets the pointer metadata represented by this `Ref`. #[inline(always)] pub(super) fn pointer_metadata(&self) -> T::PointerMetadata { // INVARIANTS: `KnownLayout::PointerMetadata` is either `()` or // `usize`. For `()`, `from_elem_count` ignores the element count; // for `usize`, it returns the element count unchanged. T::PointerMetadata::from_elem_count(self.elem_count) } }
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`. If `T: /// KnownLayout`, then `T::size_for_metadata(self.pointer_metadata())` /// returns `Some(referent.len())`. 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.bytes`'s referent. // // SAFETY: By invariant on `self`, the alignment, size, and metadata // postconditions are upheld. &self.bytes } }
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_mut` promises to return a `ByteSliceMut` whose /// referent is validly aligned for `T` and has a valid size for `T`. If /// `T: KnownLayout`, then /// `T::size_for_metadata(self.pointer_metadata())` returns /// `Some(referent.len())`. 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.bytes`'s referent. // // SAFETY: By invariant on `self`, the alignment, size, and metadata // postconditions are upheld. &mut self.bytes } }
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`). /// /// `into_byte_slice` promises to return an `IntoByteSlice` whose /// referent is validly aligned for `T` and has a valid size for `T`. If /// `T: KnownLayout`, then /// `T::size_for_metadata(self.pointer_metadata())` returns /// `Some(referent.len())`. 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.bytes`'s referent. // // SAFETY: By invariant on `self`, the alignment, size, and metadata // postconditions are upheld. self.bytes } }
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`). /// /// `into_byte_slice_mut` promises to return an `IntoByteSliceMut` whose /// referent is validly aligned for `T` and has a valid size for `T`. If /// `T: KnownLayout`, then /// `T::size_for_metadata(self.pointer_metadata())` returns /// `Some(referent.len())`. 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.bytes`'s referent. // // SAFETY: By invariant on `self`, the alignment, size, and metadata // postconditions are upheld. self.bytes } }
impl<B: CloneableByteSlice + Clone, T: ?Sized> Clone for Ref<B, T> { #[inline] fn clone(&self) -> Ref<B, T> { // INVARIANTS: Since `B: CloneableByteSlice`, `self.bytes.clone()` has // the same address and length as `self.bytes`. We copy // `self.elem_count`, so the clone also has the same metadata. Since // `self` upholds the field invariants, so does the clone. Ref { bytes: self.bytes.clone(), elem_count: self.elem_count, _marker: PhantomData } } }
// INVARIANTS: Since `B: CopyableByteSlice`, the copied `Ref`'s `bytes` has the // same address and length as the original `Ref`'s `bytes`. The copied // `elem_count` has the same metadata. 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, Safe, Unaligned}, 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: `size_of` returns `T`'s size in bytes [1]. The equality check // above therefore establishes that `bytes` has exactly that byte // length, and `validate_aligned_to` establishes alignment. // // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of.html: // // Returns the size of a type in bytes. Ok(unsafe { Ref::new_sized_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`, measured in bytes as specified // for `size_of` [1]. By safety postcondition on // `SplitByteSlice::split_at` we can rely on `split_at` to produce the // correct `bytes` and `suffix`. // // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of.html: // // Returns the size of a type in bytes. let r = unsafe { Ref::new_sized_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>()`, measured in // bytes as specified for `size_of` [1]. 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`. // // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of.html: // // Returns the size of a type in bytes. let r = unsafe { Ref::new_sized_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! /// ``` /// #[doc = codegen_section!( header = "h5", bench = "ref_type_from_bytes", format = "coco", arity = 3, [ open @index 1 @title "Sized" @variant "static_size" ], [ @index 2 @title "Unsized" @variant "dynamic_size" ], [ @index 3 @title "Dynamically Padded" @variant "dynamic_padding" ] )] #[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); let metadata = match Ptr::from_ref(source.deref()) .try_cast_into_no_leftover::<T, BecauseImmutable>(None) { Ok(ptr) => T::pointer_to_metadata(ptr.as_inner().as_ptr()), Err(e) => return Err(e.with_src(()).with_src(source)), }; // SAFETY: By its safety postcondition, `try_cast_into_no_leftover` // returned a `Ptr<T>` aligned as required for references [2], over the // same byte range as `source.deref()`. `pointer_to_metadata` returns // the metadata stored in that pointer, and `size_for_metadata` computes // the corresponding dynamically-known byte size [1]. Thus, // `T::size_for_metadata(metadata)` is `Some(source.len())`. // `ByteSlice` and its applicable subtraits guarantee that the stored // `source` continues to dereference or convert to that address and // length. These facts establish both preconditions of `new_unchecked`. // // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of_val.html: // // Returns the size of the pointed-to value in bytes. // // ... when `T` has no statically-known size ... `size_of_val` can // be used to get the dynamically-known size. // // [2] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.align_of_val.html: // // Returns the ABI-required minimum alignment of the type of the // value that `val` points to. // // Every reference to a value of the type `T` must be a multiple of // this number. Ok(unsafe { Ref::new_unchecked(source, metadata) }) }}
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! /// ``` /// #[doc = codegen_section!( header = "h5", bench = "ref_type_from_prefix", format = "coco", arity = 3, [ open @index 1 @title "Sized" @variant "static_size" ], [ @index 2 @title "Unsized" @variant "dynamic_size" ], [ @index 3 @title "Dynamically Padded" @variant "dynamic_padding" ] )] #[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 (metadata, remainder) = match Ptr::from_ref(source.deref()) .try_cast_into::<T, BecauseImmutable>(CastType::Prefix, None) { Ok((ptr, remainder)) => (T::pointer_to_metadata(ptr.as_inner().as_ptr()), 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: By its safety postcondition, `try_cast_into` returned an // `Ptr<T>` aligned as required for references [2], and a remainder // which are non-overlapping, cover `source.deref()`, and place the // `Ptr<T>` at `source.deref()`'s address. // Therefore, `split_at` is the typed pointer's byte length. By the // safety postcondition of `SplitByteSlice::split_at`, `bytes` has that // length and address. `pointer_to_metadata` returns the metadata stored // in the typed pointer, and `size_for_metadata` computes the // corresponding dynamically-known byte size [1]. Thus, // `T::size_for_metadata(metadata)` is `Some(bytes.len())`. The // `SplitByteSlice` and `ByteSlice` contracts preserve the established // address and length, satisfying both preconditions of // `new_unchecked`. // // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of_val.html: // // Returns the size of the pointed-to value in bytes. // // ... when `T` has no statically-known size ... `size_of_val` can // be used to get the dynamically-known size. // // [2] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.align_of_val.html: // // Returns the ABI-required minimum alignment of the type of the // value that `val` points to. // // Every reference to a value of the type `T` must be a multiple of // this number. let r = unsafe { Ref::new_unchecked(bytes, metadata) }; 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! /// ``` /// #[doc = codegen_section!( header = "h5", bench = "ref_type_from_suffix", format = "coco", arity = 3, [ open @index 1 @title "Sized" @variant "static_size" ], [ @index 2 @title "Unsized" @variant "dynamic_size" ], [ @index 3 @title "Dynamically Padded" @variant "dynamic_padding" ] )] #[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 (metadata, remainder) = match Ptr::from_ref(source.deref()) .try_cast_into::<T, BecauseImmutable>(CastType::Suffix, None) { Ok((ptr, remainder)) => (T::pointer_to_metadata(ptr.as_inner().as_ptr()), 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: By its safety postcondition, `try_cast_into` returned an // `Ptr<T>` aligned as required for references [2], and a remainder // which are non-overlapping, cover `source.deref()`, and place the // remainder at `source.deref()`'s address. More precisely, // `PtrInner::try_cast_into` constructs the typed suffix from the // `r_slice` produced by `split_at_unchecked(split_at)` and returns its // `l_slice` as `remainder`. Thus, even when `T` is zero-sized, the typed // pointer and the `bytes` produced by splitting `source` at // `remainder.len()` have the same address and length. By the safety // postcondition of `SplitByteSlice::split_at`, `bytes` retains that // address and length. `pointer_to_metadata` returns the metadata stored // in the typed pointer, and `size_for_metadata` computes the // corresponding dynamically-known byte size [1]. Thus, // `T::size_for_metadata(metadata)` is `Some(bytes.len())`. The // `SplitByteSlice` and `ByteSlice` contracts preserve the established // address and length, satisfying both preconditions of // `new_unchecked`. // // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of_val.html: // // Returns the size of the pointed-to value in bytes. // // ... when `T` has no statically-known size ... `size_of_val` can // be used to get the dynamically-known size. // // [2] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.align_of_val.html: // // Returns the ABI-required minimum alignment of the type of the // value that `val` points to. // // Every reference to a value of the type `T` must be a multiple of // this number. let r = unsafe { Ref::new_unchecked(bytes, metadata) }; 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! /// ``` /// #[doc = codegen_section!( header = "h5", bench = "ref_type_from_bytes_with_elems", format = "coco", arity = 2, [ open @index 1 @title "Unsized" @variant "dynamic_size" ], [ @index 2 @title "Dynamically Padded" @variant "dynamic_padding" ] )] #[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()); } if let Err(e) = Ptr::from_ref(source.deref()) .try_cast_into_no_leftover::<T, BecauseImmutable>(Some(count)) { return Err(e.with_src(()).with_src(source)); } // SAFETY: `size_for_metadata(count)` returned `expected_len`, and the // equality check established that this is `source.len()`. This is the // dynamically-known byte size described by `size_of_val` [1]. By its // safety postcondition, `try_cast_into_no_leftover(Some(count))` only // succeeded after producing a `Ptr<T>` aligned as required for // references [2], with that metadata over the same byte range as // `source.deref()`. `ByteSlice` and its applicable subtraits guarantee // that the stored `source` continues to dereference or convert to that // address and length. These facts establish both preconditions of // `new_unchecked`. // // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of_val.html: // // Returns the size of the pointed-to value in bytes. // // ... when `T` has no statically-known size ... `size_of_val` can // be used to get the dynamically-known size. // // [2] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.align_of_val.html: // // Returns the ABI-required minimum alignment of the type of the // value that `val` points to. // // Every reference to a value of the type `T` must be a multiple of // this number. Ok(unsafe { Ref::new_unchecked(source, count) }) }}
impl<B, T> Ref<B, T>where B: SplitByteSlice, T: KnownLayout<PointerMetadata = usize> + Immutable + ?Sized,{ /// Constructs a `Ref` from the prefix of 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 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-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_prefix_with_elems(&b"UU"[..], 42); // ⚠ Compile Error! /// ``` /// #[doc = codegen_section!( header = "h5", bench = "ref_type_from_prefix_with_elems", format = "coco", arity = 2, [ open @index 1 @title "Unsized" @variant "dynamic_size" ], [ @index 2 @title "Dynamically Padded" @variant "dynamic_padding" ] )] #[inline] pub fn from_prefix_with_elems( source: B, count: usize, ) -> Result<(Ref<B, T>, B), 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()), }; let (prefix, bytes) = source.split_at(expected_len).map_err(SizeError::new)?; Self::from_bytes_with_elems(prefix, count).map(move |l| (l, bytes)) }
/// Constructs a `Ref` from the suffix of the given bytes with DST length /// equal to `count` without copying. /// /// This method attempts to return a `Ref` to the suffix of `source` /// interpreted as a `T` with `count` trailing elements, 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-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_suffix_with_elems(&b"UU"[..], 42); // ⚠ Compile Error! /// ``` /// #[doc = codegen_section!( header = "h5", bench = "ref_type_from_suffix_with_elems", format = "coco", arity = 2, [ open @index 1 @title "Unsized" @variant "dynamic_size" ], [ @index 2 @title "Dynamically Padded" @variant "dynamic_padding" ] )] #[inline] pub fn from_suffix_with_elems( source: B, count: usize, ) -> Result<(B, 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()), }; let split_at = if let Some(split_at) = source.len().checked_sub(expected_len) { split_at } else { return Err(SizeError::new(source).into()); }; // SAFETY: The preceding `source.len().checked_sub(expected_len)` // guarantees that `split_at` is in-bounds. let (bytes, suffix) = unsafe { source.split_at_unchecked(split_at) }; Self::from_bytes_with_elems(suffix, count).map(move |l| (bytes, l)) }}
impl<'a, B, T> Ref<B, T>where B: 'a + IntoByteSlice<'a>, T: FromBytes + KnownLayout + Immutable + ?Sized,{ /// Converts this `Ref` into a reference. /// /// `into_ref` consumes the `Ref`, and returns a reference to `T`. /// /// Note: this is an associated function, which means that you have to call /// it as `Ref::into_ref(r)` instead of `r.into_ref()`. This is so that /// there is no conflict with a method on the inner type. /// #[doc = codegen_section!( header = "h5", bench = "ref_type_into_ref", format = "coco", arity = 3, [ open @index 1 @title "Sized" @variant "static_size" ], [ @index 2 @title "Unsized" @variant "dynamic_size" ], [ @index 3 @title "Dynamically Padded" @variant "dynamic_padding" ] )] #[must_use = "has no side effects"] #[inline(always)] pub fn into_ref(r: Self) -> &'a T { // Presumably unreachable, since we've guarded each constructor of `Ref`. static_assert_dst_is_not_zst!(T);
let metadata = r.pointer_metadata();
// SAFETY: We don't call any methods on `b` other than those provided by // `IntoByteSlice`. let b = unsafe { r.into_byte_slice() }; let b = b.into_byte_slice();
if let crate::layout::SizeInfo::Sized { .. } = T::LAYOUT.size_info { let ptr = Ptr::from_ref(b); // SAFETY: We just checked that `T: Sized`. By invariant on `r`, // `b`'s size is equal to `size_of::<T>()`. let ptr = unsafe { cast_for_sized::<T, _, _, _>(ptr) };
// SAFETY: None of the preceding transformations modifies the // address of the pointer, and by invariant on `r`, we know that it // is validly-aligned. let ptr = unsafe { ptr.assume_alignment::<Aligned>() }; return ptr.as_ref(); }
// PANICS: By post-condition on `into_byte_slice`, `b` is aligned for // `T`, and its size is exactly the size encoded by `metadata`. By // post-condition, `b.into_byte_slice()` produces a byte slice with // identical address and length to that produced by `b.deref()`. let ptr = Ptr::from_ref(b.into_byte_slice()) .try_cast_into_no_leftover::<T, BecauseImmutable>(Some(metadata)) .expect("zerocopy internal error: into_ref should be infallible"); let ptr = ptr.recall_validity(); ptr.as_ref() }}
impl<'a, B, T> Ref<B, T>where B: 'a + IntoByteSliceMut<'a>, T: FromBytes + IntoBytes + KnownLayout + ?Sized,{ /// Converts this `Ref` into a mutable reference. /// /// `into_mut` consumes the `Ref`, and returns a mutable reference to `T`. /// /// Note: this is an associated function, which means that you have to call /// it as `Ref::into_mut(r)` instead of `r.into_mut()`. This is so that /// there is no conflict with a method on the inner type. /// #[doc = codegen_section!( header = "h5", bench = "ref_type_into_mut", format = "coco", arity = 2, [ open @index 1 @title "Sized" @variant "static_size" ], [ @index 2 @title "Unsized" @variant "dynamic_size" ] )] #[must_use = "has no side effects"] #[inline(always)] pub fn into_mut(r: Self) -> &'a mut T { // Presumably unreachable, since we've guarded each constructor of `Ref`. static_assert_dst_is_not_zst!(T);
let metadata = r.pointer_metadata();
// SAFETY: We don't call any methods on `b` other than those provided by // `IntoByteSliceMut`. let b = unsafe { r.into_byte_slice_mut() }; let b = b.into_byte_slice_mut();
if let crate::layout::SizeInfo::Sized { .. } = T::LAYOUT.size_info { let ptr = Ptr::from_mut(b); // SAFETY: We just checked that `T: Sized`. By invariant on `r`, // `b`'s size is equal to `size_of::<T>()`. let ptr = unsafe { cast_for_sized::< T, _, (BecauseRead, BecauseExclusive), (BecauseMutationCompatible, BecauseSharedCompatible), >(ptr) };
// SAFETY: None of the preceding transformations modifies the // address of the pointer, and by invariant on `r`, we know that it // is validly-aligned. let ptr = unsafe { ptr.assume_alignment::<Aligned>() }; return ptr.as_mut(); }
// PANICS: By post-condition on `into_byte_slice_mut`, `b` is aligned // for `T`, and its size is exactly the size encoded by `metadata`. By // post-condition, `b.into_byte_slice_mut()` produces a byte slice with // identical address and length to that produced by `b.deref_mut()`. let ptr = Ptr::from_mut(b.into_byte_slice_mut()) .try_cast_into_no_leftover::<T, BecauseExclusive>(Some(metadata)) .expect("zerocopy internal error: into_mut should be infallible"); let ptr = ptr.recall_validity::<_, (_, (_, _))>(); ptr.as_mut() }}
impl<B, T> Ref<B, T>where B: ByteSlice, T: ?Sized,{ /// Gets the underlying bytes. /// /// Note: this is an associated function, which means that you have to call /// it as `Ref::bytes(r)` instead of `r.bytes()`. This is so that there is /// no conflict with a method on the inner type. /// #[doc = codegen_section!( header = "h5", bench = "ref_type_bytes", format = "coco", arity = 3, [ open @index 1 @title "Sized" @variant "static_size" ], [ @index 2 @title "Unsized" @variant "dynamic_size" ], [ @index 3 @title "Dynamically Padded" @variant "dynamic_padding" ] )] #[inline] pub fn bytes(r: &Self) -> &[u8] { // SAFETY: We don't call any methods on `b` other than those provided by // `ByteSlice`. unsafe { r.as_byte_slice().deref() } }}
impl<B, T> Ref<B, T>where B: ByteSliceMut, T: ?Sized,{ /// Gets the underlying bytes mutably. /// /// Note: this is an associated function, which means that you have to call /// it as `Ref::bytes_mut(r)` instead of `r.bytes_mut()`. This is so that /// there is no conflict with a method on the inner type. /// #[doc = codegen_section!( header = "h5", bench = "ref_type_bytes_mut", format = "coco", arity = 3, [ open @index 1 @title "Sized" @variant "static_size" ], [ @index 2 @title "Unsized" @variant "dynamic_size" ], [ @index 3 @title "Dynamically Padded" @variant "dynamic_padding" ] )] #[inline] pub fn bytes_mut(r: &mut Self) -> &mut [u8] { // SAFETY: We don't call any methods on `b` other than those provided by // `ByteSliceMut`. unsafe { r.as_byte_slice_mut().deref_mut() } }}
impl<B, T> Ref<B, T>where B: ByteSlice, T: FromBytes,{ /// Reads a copy of `T`. /// /// Note: this is an associated function, which means that you have to call /// it as `Ref::read(r)` instead of `r.read()`. This is so that there is no /// conflict with a method on the inner type. /// #[doc = codegen_section!( header = "h5", bench = "ref_type_read_static_size", format = "coco_static_size", )] #[must_use = "has no side effects"] #[inline] pub fn read(r: &Self) -> T { // SAFETY: We don't call any methods on `b` other than those provided by // `ByteSlice`. let b = unsafe { r.as_byte_slice() };
// SAFETY: By postcondition on `as_byte_slice`, we know that `b` is a // valid size and alignment for `T`. By safety invariant on `ByteSlice`, // we know that this is preserved via `.deref()`. Because `T: // FromBytes`, it is sound to interpret these bytes as a `T`. unsafe { ptr::read(b.deref().as_ptr().cast::<T>()) } }}
impl<B, T> Ref<B, T>where B: ByteSliceMut, T: IntoBytes,{ /// Writes the bytes of `t` and then forgets `t`. /// /// Note: this is an associated function, which means that you have to call /// it as `Ref::write(r, t)` instead of `r.write(t)`. This is so that there /// is no conflict with a method on the inner type. /// #[doc = codegen_section!( header = "h5", bench = "ref_type_write_static_size", format = "coco_static_size", )] #[inline] pub fn write(r: &mut Self, t: T) { // SAFETY: We don't call any methods on `b` other than those provided by // `ByteSliceMut`. let b = unsafe { r.as_byte_slice_mut() };
// SAFETY: By postcondition on `as_byte_slice_mut`, we know that `b` is a // valid size and alignment for `T`. By safety invariant on // `ByteSlice`, we know that this is preserved via `.deref()`. Writing // `t` to the buffer will allow all of the bytes of `t` to be accessed // as a `[u8]`, but because `T: IntoBytes`, we know that this is sound. unsafe { ptr::write(b.deref_mut().as_mut_ptr().cast::<T>(), t) } }}
impl<B, T> Deref for Ref<B, T>where B: ByteSlice, T: FromBytes + KnownLayout + Immutable + ?Sized,{ type Target = T;
/// Dereferences the value. /// #[doc = codegen_section!( header = "h5", bench = "ref_type_deref", format = "coco", arity = 3, [ open @index 1 @title "Sized" @variant "static_size" ], [ @index 2 @title "Unsized" @variant "dynamic_size" ], [ @index 3 @title "Dynamically Padded" @variant "dynamic_padding" ] )] #[inline] fn deref(&self) -> &T { // Presumably unreachable, since we've guarded each constructor of `Ref`. static_assert_dst_is_not_zst!(T);
let metadata = self.pointer_metadata();
// SAFETY: We don't call any methods on `b` other than those provided by // `ByteSlice`. let b = unsafe { self.as_byte_slice() }; let b = b.deref();
if let crate::layout::SizeInfo::Sized { .. } = T::LAYOUT.size_info { let ptr = Ptr::from_ref(b); // SAFETY: We just checked that `T: Sized`. By invariant on `r`, // `b`'s size is equal to `size_of::<T>()`. let ptr = unsafe { cast_for_sized::<T, _, _, _>(ptr) };
// SAFETY: None of the preceding transformations modifies the // address of the pointer, and by invariant on `r`, we know that it // is validly-aligned. let ptr = unsafe { ptr.assume_alignment::<Aligned>() }; return ptr.as_ref(); }
// PANICS: By postcondition on `as_byte_slice`, `b` is aligned for `T`, // and its size is exactly the size encoded by `metadata`. By invariant // on `ByteSlice`, these are preserved through `.deref()`, so this // `unwrap` will not panic. let ptr = Ptr::from_ref(b) .try_cast_into_no_leftover::<T, BecauseImmutable>(Some(metadata)) .expect("zerocopy internal error: Deref::deref should be infallible"); let ptr = ptr.recall_validity(); ptr.as_ref() }}
impl<B, T> DerefMut for Ref<B, T>where B: ByteSliceMut, // FIXME(#251): We can't remove `Immutable` here because it's required by // the impl of `Deref`, which is a super-trait of `DerefMut`. Maybe we can // add a separate inherent method for this? T: FromBytes + IntoBytes + KnownLayout + Immutable + ?Sized,{ /// Mutably dereferences the value. /// #[doc = codegen_section!( header = "h5", bench = "ref_type_deref_mut", format = "coco", arity = 2, [ open @index 1 @title "Sized" @variant "static_size" ], [ @index 2 @title "Unsized" @variant "dynamic_size" ] )] #[inline] fn deref_mut(&mut self) -> &mut T { // Presumably unreachable, since we've guarded each constructor of `Ref`. static_assert_dst_is_not_zst!(T);
let metadata = self.pointer_metadata();
// SAFETY: We don't call any methods on `b` other than those provided by // `ByteSliceMut`. let b = unsafe { self.as_byte_slice_mut() }; let b = b.deref_mut();
if let crate::layout::SizeInfo::Sized { .. } = T::LAYOUT.size_info { let ptr = Ptr::from_mut(b); // SAFETY: We just checked that `T: Sized`. By invariant on `r`, // `b`'s size is equal to `size_of::<T>()`. let ptr = unsafe { cast_for_sized::< T, _, (BecauseRead, BecauseExclusive), (BecauseMutationCompatible, BecauseSharedCompatible), >(ptr) };
// SAFETY: None of the preceding transformations modifies the // address of the pointer, and by invariant on `r`, we know that it // is validly-aligned. let ptr = unsafe { ptr.assume_alignment::<Aligned>() }; return ptr.as_mut(); }
// PANICS: By postcondition on `as_byte_slice_mut`, `b` is aligned for // `T`, and its size is exactly the size encoded by `metadata`. By // invariant on `ByteSlice`, these are preserved through `.deref_mut()`, // so this `unwrap` will not panic. let ptr = Ptr::from_mut(b) .try_cast_into_no_leftover::<T, BecauseExclusive>(Some(metadata)) .expect("zerocopy internal error: DerefMut::deref_mut should be infallible"); let ptr = ptr.recall_validity::<_, (_, (_, BecauseExclusive))>(); ptr.as_mut() }}
impl<T, B> Display for Ref<B, T>where B: ByteSlice, T: FromBytes + Display + KnownLayout + Immutable + ?Sized,{ #[inline] fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { let inner: &T = self; inner.fmt(fmt) }}
impl<T, B> Debug for Ref<B, T>where B: ByteSlice, T: FromBytes + Debug + KnownLayout + Immutable + ?Sized,{ #[inline] fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { let inner: &T = self; fmt.debug_tuple("Ref").field(&inner).finish() }}
impl<T, B> Eq for Ref<B, T>where B: ByteSlice, T: FromBytes + Eq + KnownLayout + Immutable + ?Sized,{}
impl<T, B> PartialEq for Ref<B, T>where B: ByteSlice, T: FromBytes + PartialEq + KnownLayout + Immutable + ?Sized,{ #[inline] fn eq(&self, other: &Self) -> bool { self.deref().eq(other.deref()) }}
impl<T, B> Ord for Ref<B, T>where B: ByteSlice, T: FromBytes + Ord + KnownLayout + Immutable + ?Sized,{ #[inline] fn cmp(&self, other: &Self) -> Ordering { let inner: &T = self; let other_inner: &T = other; inner.cmp(other_inner) }}
impl<T, B> PartialOrd for Ref<B, T>where B: ByteSlice, T: FromBytes + PartialOrd + KnownLayout + Immutable + ?Sized,{ #[inline] fn partial_cmp(&self, other: &Self) -> Option<Ordering> { let inner: &T = self; let other_inner: &T = other; inner.partial_cmp(other_inner) }}
/// # Safety////// `T: Sized` and `ptr`'s referent must have size `size_of::<T>()`.#[inline(always)]unsafe fn cast_for_sized<'a, T, A, R, S>( ptr: Ptr<'a, [u8], (A, Aligned, Safe)>,) -> Ptr<'a, T, (A, Unaligned, Safe)>where T: FromBytes + KnownLayout + ?Sized, A: crate::invariant::Aliasing, [u8]: MutationCompatible<T, A, Initialized, Initialized, R>, T: TransmuteFromPtr<T, A, Initialized, Safe, crate::pointer::cast::IdCast, S>,{ use crate::pointer::cast::{Cast, Project};
enum CastForSized {}
// SAFETY: `CastForSized` is only used below with the input `ptr`, which the // caller promises has size `size_of::<T>()`. Thus, the referent produced in // this cast has the same size as `ptr`'s referent. All operations preserve // provenance. unsafe impl<T: ?Sized + KnownLayout> Project<[u8], T> for CastForSized { #[inline(always)] fn project(src: PtrInner<'_, [u8]>) -> *mut T { T::raw_from_ptr_len( src.as_non_null().cast(), <T::PointerMetadata as crate::PointerMetadata>::from_elem_count(0), ) .as_ptr() } }
// SAFETY: The `Project::project` impl preserves referent address. unsafe impl<T: ?Sized + KnownLayout> Cast<[u8], T> for CastForSized {}
ptr.recall_validity::<Initialized, (_, (_, _))>() .cast::<_, CastForSized, _>() .recall_validity::<Safe, _>()}
#[cfg(test)]#[allow(clippy::assertions_on_result_states)]mod tests { use core::convert::TryInto as _;
use super::*; use crate::util::testutil::*;
#[test] fn test_mut_slice_into_ref() { // Prior to #1260/#1299, calling `into_ref` on a `&mut [u8]`-backed // `Ref` was not supported. let mut buf = [0u8]; let r = Ref::<&mut [u8], u8>::from_bytes(&mut buf).unwrap(); assert_eq!(Ref::into_ref(r), &0); }
#[test] fn test_address() { // Test that the `Deref` and `DerefMut` implementations return a // reference which points to the right region of memory.
let buf = [0]; let r = Ref::<_, u8>::from_bytes(&buf[..]).unwrap(); let buf_ptr = buf.as_ptr(); let deref_ptr: *const u8 = r.deref(); assert_eq!(buf_ptr, deref_ptr);
let buf = [0]; let r = Ref::<_, [u8]>::from_bytes(&buf[..]).unwrap(); let buf_ptr = buf.as_ptr(); let deref_ptr = r.deref().as_ptr(); assert_eq!(buf_ptr, deref_ptr); }
#[test] #[allow(clippy::clone_on_copy)] // Exercise `Ref`'s manual `Clone` impl. fn test_with_elems_preserves_ambiguous_metadata() { #[derive(FromBytes, Immutable, KnownLayout)] #[repr(C, align(8))] struct Frame { header: [u8; 8], body: [u8], }
#[derive(FromBytes, Immutable, KnownLayout)] #[repr(C, align(8))] struct OddHeader { header: [u8; 7], body: [u8], }
// Dynamic trailing padding makes these pairs of distinct element // counts produce the same total byte size. Thus, the byte length alone // cannot recover the count supplied to a `*_with_elems` constructor. assert_eq!(Frame::size_for_metadata(1), Some(16)); assert_eq!(Frame::size_for_metadata(8), Some(16)); assert_eq!(OddHeader::size_for_metadata(0), Some(8)); assert_eq!(OddHeader::size_for_metadata(1), Some(8));
let bytes = Align::<[u8; 32], AU64>::default();
let whole = Ref::<_, Frame>::from_bytes_with_elems(&bytes.t[..16], 1).unwrap(); assert_eq!(whole.body.len(), 1); assert_eq!(Ref::bytes(&whole).len(), 16); assert_eq!(whole.clone().body.len(), 1); let copied = whole; assert_eq!(copied.body.len(), 1); assert_eq!(Ref::into_ref(whole).body.len(), 1);
let (prefix, rest) = Ref::<_, Frame>::from_prefix_with_elems(&bytes.t[..], 1).unwrap(); assert_eq!(prefix.body.len(), 1); assert_eq!(rest.len(), 16);
let (before, suffix) = Ref::<_, Frame>::from_suffix_with_elems(&bytes.t[..24], 1).unwrap(); assert_eq!(before.len(), 8); assert_eq!(suffix.body.len(), 1);
// Zero is real metadata, not a sentinel for "infer from the bytes". let empty = Ref::<_, OddHeader>::from_bytes_with_elems(&bytes.t[..8], 0).unwrap(); assert!(empty.body.is_empty()); assert!(Ref::into_ref(empty).body.is_empty());
// The implicit constructors still choose the largest fitting count, // and retain the metadata selected during their validating cast. let inferred = Ref::<_, Frame>::from_bytes(&bytes.t[..16]).unwrap(); assert_eq!(inferred.body.len(), 8); let (inferred, rest) = Ref::<_, Frame>::from_prefix(&bytes.t[..16]).unwrap(); assert_eq!(inferred.body.len(), 8); assert!(rest.is_empty()); let (before, inferred) = Ref::<_, Frame>::from_suffix(&bytes.t[..16]).unwrap(); assert!(before.is_empty()); assert_eq!(inferred.body.len(), 8); }
// Verify that values written to a `Ref` are properly shared between the // typed and untyped representations, that reads via `deref` and `read` // behave the same, and that writes via `deref_mut` and `write` behave the // same. fn test_new_helper(mut r: Ref<&mut [u8], AU64>) { // assert that the value starts at 0 assert_eq!(*r, AU64(0)); assert_eq!(Ref::read(&r), AU64(0));
// Assert that values written to the typed value are reflected in the // byte slice. const VAL1: AU64 = AU64(0xFF00FF00FF00FF00); *r = VAL1; assert_eq!(Ref::bytes(&r), &VAL1.to_bytes()); *r = AU64(0); Ref::write(&mut r, VAL1); assert_eq!(Ref::bytes(&r), &VAL1.to_bytes());
// Assert that values written to the byte slice are reflected in the // typed value. const VAL2: AU64 = AU64(!VAL1.0); // different from `VAL1` Ref::bytes_mut(&mut r).copy_from_slice(&VAL2.to_bytes()[..]); assert_eq!(*r, VAL2); assert_eq!(Ref::read(&r), VAL2); }
// Verify that values written to a `Ref` are properly shared between the // typed and untyped representations; pass a value with `typed_len` `AU64`s // backed by an array of `typed_len * 8` bytes. fn test_new_helper_slice(mut r: Ref<&mut [u8], [AU64]>, typed_len: usize) { // Assert that the value starts out zeroed. assert_eq!(&*r, vec![AU64(0); typed_len].as_slice());
// Check the backing storage is the exact same slice. let untyped_len = typed_len * 8; assert_eq!(Ref::bytes(&r).len(), untyped_len); assert_eq!(Ref::bytes(&r).as_ptr(), r.as_ptr().cast::<u8>());
// Assert that values written to the typed value are reflected in the // byte slice. const VAL1: AU64 = AU64(0xFF00FF00FF00FF00); for typed in &mut *r { *typed = VAL1; } assert_eq!(Ref::bytes(&r), VAL1.0.to_ne_bytes().repeat(typed_len).as_slice());
// Assert that values written to the byte slice are reflected in the // typed value. const VAL2: AU64 = AU64(!VAL1.0); // different from VAL1 Ref::bytes_mut(&mut r).copy_from_slice(&VAL2.0.to_ne_bytes().repeat(typed_len)); assert!(r.iter().copied().all(|x| x == VAL2)); }
#[test] fn test_new_aligned_sized() { // Test that a properly-aligned, properly-sized buffer works for new, // new_from_prefix, and new_from_suffix, and that new_from_prefix and // new_from_suffix return empty slices. Test that a properly-aligned // buffer whose length is a multiple of the element size works for // new_slice.
// A buffer with an alignment of 8. let mut buf = Align::<[u8; 8], AU64>::default(); // `buf.t` should be aligned to 8, so this should always succeed. test_new_helper(Ref::<_, AU64>::from_bytes(&mut buf.t[..]).unwrap()); { // In a block so that `r` and `suffix` don't live too long. buf.set_default(); let (r, suffix) = Ref::<_, AU64>::from_prefix(&mut buf.t[..]).unwrap(); assert!(suffix.is_empty()); test_new_helper(r); } { buf.set_default(); let (prefix, r) = Ref::<_, AU64>::from_suffix(&mut buf.t[..]).unwrap(); assert!(prefix.is_empty()); test_new_helper(r); }
// A buffer with alignment 8 and length 24. We choose this length very // intentionally: if we instead used length 16, then the prefix and // suffix lengths would be identical. In the past, we used length 16, // which resulted in this test failing to discover the bug uncovered in // #506. let mut buf = Align::<[u8; 24], AU64>::default(); // `buf.t` should be aligned to 8 and have a length which is a multiple // of `size_of::<AU64>()`, so this should always succeed. test_new_helper_slice(Ref::<_, [AU64]>::from_bytes(&mut buf.t[..]).unwrap(), 3); buf.set_default(); let r = Ref::<_, [AU64]>::from_bytes_with_elems(&mut buf.t[..], 3).unwrap(); test_new_helper_slice(r, 3);
let ascending: [u8; 24] = (0..24).collect::<Vec<_>>().try_into().unwrap(); // 16 ascending bytes followed by 8 zeros. let mut ascending_prefix = ascending; ascending_prefix[16..].copy_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0]); // 8 zeros followed by 16 ascending bytes. let mut ascending_suffix = ascending; ascending_suffix[..8].copy_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0]); { buf.t = ascending_suffix; let (r, suffix) = Ref::<_, [AU64]>::from_prefix_with_elems(&mut buf.t[..], 1).unwrap(); assert_eq!(suffix, &ascending[8..]); test_new_helper_slice(r, 1); } { buf.t = ascending_prefix; let (prefix, r) = Ref::<_, [AU64]>::from_suffix_with_elems(&mut buf.t[..], 1).unwrap(); assert_eq!(prefix, &ascending[..16]); test_new_helper_slice(r, 1); } }
#[test] fn test_new_oversized() { // Test that a properly-aligned, overly-sized buffer works for // `new_from_prefix` and `new_from_suffix`, and that they return the // remainder and prefix of the slice respectively.
let mut buf = Align::<[u8; 16], AU64>::default(); { // In a block so that `r` and `suffix` don't live too long. `buf.t` // should be aligned to 8, so this should always succeed. let (r, suffix) = Ref::<_, AU64>::from_prefix(&mut buf.t[..]).unwrap(); assert_eq!(suffix.len(), 8); test_new_helper(r); } { buf.set_default(); // `buf.t` should be aligned to 8, so this should always succeed. let (prefix, r) = Ref::<_, AU64>::from_suffix(&mut buf.t[..]).unwrap(); assert_eq!(prefix.len(), 8); test_new_helper(r); } }
#[test] #[allow(clippy::cognitive_complexity)] fn test_new_error() { // Fail because the buffer is too large.
// A buffer with an alignment of 8. let buf = Align::<[u8; 16], AU64>::default(); // `buf.t` should be aligned to 8, so only the length check should fail. assert!(Ref::<_, AU64>::from_bytes(&buf.t[..]).is_err());
// Fail because the buffer is too small.
// A buffer with an alignment of 8. let buf = Align::<[u8; 4], AU64>::default(); // `buf.t` should be aligned to 8, so only the length check should fail. assert!(Ref::<_, AU64>::from_bytes(&buf.t[..]).is_err()); assert!(Ref::<_, AU64>::from_prefix(&buf.t[..]).is_err()); assert!(Ref::<_, AU64>::from_suffix(&buf.t[..]).is_err());
// Fail because the length is not a multiple of the element size.
let buf = Align::<[u8; 12], AU64>::default(); // `buf.t` has length 12, but element size is 8. assert!(Ref::<_, [AU64]>::from_bytes(&buf.t[..]).is_err());
// Fail because the buffer is too short. let buf = Align::<[u8; 12], AU64>::default(); // `buf.t` has length 12, but the element size is 8 (and we're expecting // two of them). For each function, we test with a length that would // cause the size to overflow `usize`, and with a normal length that // will fail thanks to the buffer being too short; these are different // error paths, and while the error types are the same, the distinction // shows up in code coverage metrics. let n = (usize::MAX / mem::size_of::<AU64>()) + 1; assert!(Ref::<_, [AU64]>::from_bytes_with_elems(&buf.t[..], n).is_err()); assert!(Ref::<_, [AU64]>::from_bytes_with_elems(&buf.t[..], 2).is_err()); assert!(Ref::<_, [AU64]>::from_prefix_with_elems(&buf.t[..], n).is_err()); assert!(Ref::<_, [AU64]>::from_prefix_with_elems(&buf.t[..], 2).is_err()); assert!(Ref::<_, [AU64]>::from_suffix_with_elems(&buf.t[..], n).is_err()); assert!(Ref::<_, [AU64]>::from_suffix_with_elems(&buf.t[..], 2).is_err());
// Fail because the alignment is insufficient.
// A buffer with an alignment of 8. An odd buffer size is chosen so that // the last byte of the buffer has odd alignment. let buf = Align::<[u8; 13], AU64>::default(); // Slicing from 1, we get a buffer with size 12 (so the length check // should succeed) but an alignment of only 1, which is insufficient. assert!(Ref::<_, AU64>::from_bytes(&buf.t[1..]).is_err()); assert!(Ref::<_, AU64>::from_prefix(&buf.t[1..]).is_err()); assert!(Ref::<_, [AU64]>::from_bytes(&buf.t[1..]).is_err()); assert!(Ref::<_, [AU64]>::from_bytes_with_elems(&buf.t[1..], 1).is_err()); assert!(Ref::<_, [AU64]>::from_prefix_with_elems(&buf.t[1..], 1).is_err()); assert!(Ref::<_, [AU64]>::from_suffix_with_elems(&buf.t[1..], 1).is_err()); // Slicing is unnecessary here because `new_from_suffix` uses the suffix // of the slice, which has odd alignment. assert!(Ref::<_, AU64>::from_suffix(&buf.t[..]).is_err());
// Fail due to arithmetic overflow.
let buf = Align::<[u8; 16], AU64>::default(); let unreasonable_len = usize::MAX / mem::size_of::<AU64>() + 1; assert!(Ref::<_, [AU64]>::from_prefix_with_elems(&buf.t[..], unreasonable_len).is_err()); assert!(Ref::<_, [AU64]>::from_suffix_with_elems(&buf.t[..], unreasonable_len).is_err()); }
#[test] #[allow(unstable_name_collisions)] #[allow(clippy::as_conversions)] fn test_into_ref_mut() { #[allow(unused)] use crate::util::AsAddress as _;
let mut buf = Align::<[u8; 8], u64>::default(); let r = Ref::<_, u64>::from_bytes(&buf.t[..]).unwrap(); let rf = Ref::into_ref(r); assert_eq!(rf, &0u64); let buf_addr = (&buf.t as *const [u8; 8]).addr(); assert_eq!((rf as *const u64).addr(), buf_addr);
let r = Ref::<_, u64>::from_bytes(&mut buf.t[..]).unwrap(); let rf = Ref::into_mut(r); assert_eq!(rf, &mut 0u64); assert_eq!((rf as *mut u64).addr(), buf_addr);
*rf = u64::MAX; assert_eq!(buf.t, [0xFF; 8]);
// Exercise the unsized `into_mut` route, which must use the metadata // retained by the constructor rather than infer fresh metadata. let mut buf = Align::<[u8; 8], u16>::default(); let r = Ref::<_, [u16]>::from_bytes_with_elems(&mut buf.t[..], 4).unwrap(); let rf = Ref::into_mut(r); assert_eq!(rf.len(), 4); }
#[test] fn test_display_debug() { let buf = Align::<[u8; 8], u64>::default(); let r = Ref::<_, u64>::from_bytes(&buf.t[..]).unwrap(); assert_eq!(format!("{}", r), "0"); assert_eq!(format!("{:?}", r), "Ref(0)");
let buf = Align::<[u8; 8], u64>::default(); let r = Ref::<_, [u64]>::from_bytes(&buf.t[..]).unwrap(); assert_eq!(format!("{:?}", r), "Ref([0])"); }
#[test] fn test_eq() { let buf1 = 0_u64; let r1 = Ref::<_, u64>::from_bytes(buf1.as_bytes()).unwrap(); let buf2 = 0_u64; let r2 = Ref::<_, u64>::from_bytes(buf2.as_bytes()).unwrap(); assert_eq!(r1, r2); }
#[test] fn test_ne() { let buf1 = 0_u64; let r1 = Ref::<_, u64>::from_bytes(buf1.as_bytes()).unwrap(); let buf2 = 1_u64; let r2 = Ref::<_, u64>::from_bytes(buf2.as_bytes()).unwrap(); assert_ne!(r1, r2); }
#[test] fn test_ord() { let buf1 = 0_u64; let r1 = Ref::<_, u64>::from_bytes(buf1.as_bytes()).unwrap(); let buf2 = 1_u64; let r2 = Ref::<_, u64>::from_bytes(buf2.as_bytes()).unwrap(); assert!(r1 < r2); assert_eq!(PartialOrd::partial_cmp(&r1, &r2), Some(Ordering::Less)); assert_eq!(Ord::cmp(&r1, &r2), Ordering::Less); }}
#[cfg(all(test, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS))]mod benches { use test::{self, Bencher};
use super::*; use crate::util::testutil::*;
#[bench] fn bench_from_bytes_sized(b: &mut Bencher) { let buf = Align::<[u8; 8], AU64>::default(); // `buf.t` should be aligned to 8, so this should always succeed. let bytes = &buf.t[..]; b.iter(|| test::black_box(Ref::<_, AU64>::from_bytes(test::black_box(bytes)).unwrap())); }
#[bench] fn bench_into_ref_sized(b: &mut Bencher) { let buf = Align::<[u8; 8], AU64>::default(); let bytes = &buf.t[..]; let r = Ref::<_, AU64>::from_bytes(bytes).unwrap(); b.iter(|| test::black_box(Ref::into_ref(test::black_box(r)))); }
#[bench] fn bench_into_mut_sized(b: &mut Bencher) { let mut buf = Align::<[u8; 8], AU64>::default(); let buf = &mut buf.t[..]; let _ = Ref::<_, AU64>::from_bytes(&mut *buf).unwrap(); b.iter(move || { // SAFETY: The preceding `from_bytes` succeeded, and so we know that // `buf` is validly aligned and has the `size_of::<AU64>()` byte // length required by `new_sized_unchecked` [1]. // // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of.html: // // Returns the size of a type in bytes. let r = unsafe { Ref::<&mut [u8], AU64>::new_sized_unchecked(&mut *buf) }; test::black_box(Ref::into_mut(test::black_box(r))); }); }
#[bench] fn bench_deref_sized(b: &mut Bencher) { let buf = Align::<[u8; 8], AU64>::default(); let bytes = &buf.t[..]; let r = Ref::<_, AU64>::from_bytes(bytes).unwrap(); b.iter(|| { let temp = test::black_box(r); test::black_box(temp.deref()); }); }
#[bench] fn bench_deref_mut_sized(b: &mut Bencher) { let mut buf = Align::<[u8; 8], AU64>::default(); let buf = &mut buf.t[..]; let _ = Ref::<_, AU64>::from_bytes(&mut *buf).unwrap(); b.iter(|| { // SAFETY: The preceding `from_bytes` succeeded, and so we know that // `buf` is validly aligned and has the `size_of::<AU64>()` byte // length required by `new_sized_unchecked` [1]. // // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of.html: // // Returns the size of a type in bytes. let r = unsafe { Ref::<&mut [u8], AU64>::new_sized_unchecked(&mut *buf) }; let mut temp = test::black_box(r); test::black_box(temp.deref_mut()); }); }}