1*c3739801SMiguel Ojeda // Copyright 2024 The Fuchsia Authors 2*c3739801SMiguel Ojeda // 3*c3739801SMiguel Ojeda // Licensed under the 2-Clause BSD License <LICENSE-BSD or 4*c3739801SMiguel Ojeda // https://opensource.org/license/bsd-2-clause>, Apache License, Version 2.0 5*c3739801SMiguel Ojeda // <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT 6*c3739801SMiguel Ojeda // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option. 7*c3739801SMiguel Ojeda // This file may not be copied, modified, or distributed except according to 8*c3739801SMiguel Ojeda // those terms. 9*c3739801SMiguel Ojeda use super::*; 10*c3739801SMiguel Ojeda use crate::pointer::{ 11*c3739801SMiguel Ojeda BecauseInvariantsEq, BecauseMutationCompatible, MutationCompatible, TransmuteFromPtr, 12*c3739801SMiguel Ojeda }; 13*c3739801SMiguel Ojeda 14*c3739801SMiguel Ojeda mod def { 15*c3739801SMiguel Ojeda use core::marker::PhantomData; 16*c3739801SMiguel Ojeda 17*c3739801SMiguel Ojeda use crate::{ 18*c3739801SMiguel Ojeda ByteSlice, ByteSliceMut, CloneableByteSlice, CopyableByteSlice, IntoByteSlice, 19*c3739801SMiguel Ojeda IntoByteSliceMut, 20*c3739801SMiguel Ojeda }; 21*c3739801SMiguel Ojeda 22*c3739801SMiguel Ojeda /// A typed reference derived from a byte slice. 23*c3739801SMiguel Ojeda /// 24*c3739801SMiguel Ojeda /// A `Ref<B, T>` is a reference to a `T` which is stored in a byte slice, `B`. 25*c3739801SMiguel Ojeda /// Unlike a native reference (`&T` or `&mut T`), `Ref<B, T>` has the same 26*c3739801SMiguel Ojeda /// mutability as the byte slice it was constructed from (`B`). 27*c3739801SMiguel Ojeda /// 28*c3739801SMiguel Ojeda /// # Examples 29*c3739801SMiguel Ojeda /// 30*c3739801SMiguel Ojeda /// `Ref` can be used to treat a sequence of bytes as a structured type, and 31*c3739801SMiguel Ojeda /// to read and write the fields of that type as if the byte slice reference 32*c3739801SMiguel Ojeda /// were simply a reference to that type. 33*c3739801SMiguel Ojeda /// 34*c3739801SMiguel Ojeda /// ```rust 35*c3739801SMiguel Ojeda /// use zerocopy::*; 36*c3739801SMiguel Ojeda /// # use zerocopy_derive::*; 37*c3739801SMiguel Ojeda /// 38*c3739801SMiguel Ojeda /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)] 39*c3739801SMiguel Ojeda /// #[repr(C)] 40*c3739801SMiguel Ojeda /// struct UdpHeader { 41*c3739801SMiguel Ojeda /// src_port: [u8; 2], 42*c3739801SMiguel Ojeda /// dst_port: [u8; 2], 43*c3739801SMiguel Ojeda /// length: [u8; 2], 44*c3739801SMiguel Ojeda /// checksum: [u8; 2], 45*c3739801SMiguel Ojeda /// } 46*c3739801SMiguel Ojeda /// 47*c3739801SMiguel Ojeda /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)] 48*c3739801SMiguel Ojeda /// #[repr(C, packed)] 49*c3739801SMiguel Ojeda /// struct UdpPacket { 50*c3739801SMiguel Ojeda /// header: UdpHeader, 51*c3739801SMiguel Ojeda /// body: [u8], 52*c3739801SMiguel Ojeda /// } 53*c3739801SMiguel Ojeda /// 54*c3739801SMiguel Ojeda /// impl UdpPacket { 55*c3739801SMiguel Ojeda /// pub fn parse<B: ByteSlice>(bytes: B) -> Option<Ref<B, UdpPacket>> { 56*c3739801SMiguel Ojeda /// Ref::from_bytes(bytes).ok() 57*c3739801SMiguel Ojeda /// } 58*c3739801SMiguel Ojeda /// } 59*c3739801SMiguel Ojeda /// ``` 60*c3739801SMiguel Ojeda pub struct Ref<B, T: ?Sized>( 61*c3739801SMiguel Ojeda // INVARIANTS: The referent (via `.deref`, `.deref_mut`, `.into`) byte 62*c3739801SMiguel Ojeda // slice is aligned to `T`'s alignment and its size corresponds to a 63*c3739801SMiguel Ojeda // valid size for `T`. 64*c3739801SMiguel Ojeda B, 65*c3739801SMiguel Ojeda PhantomData<T>, 66*c3739801SMiguel Ojeda ); 67*c3739801SMiguel Ojeda 68*c3739801SMiguel Ojeda impl<B, T: ?Sized> Ref<B, T> { 69*c3739801SMiguel Ojeda /// Constructs a new `Ref`. 70*c3739801SMiguel Ojeda /// 71*c3739801SMiguel Ojeda /// # Safety 72*c3739801SMiguel Ojeda /// 73*c3739801SMiguel Ojeda /// `bytes` dereferences (via [`deref`], [`deref_mut`], and [`into`]) to 74*c3739801SMiguel Ojeda /// a byte slice which is aligned to `T`'s alignment and whose size is a 75*c3739801SMiguel Ojeda /// valid size for `T`. 76*c3739801SMiguel Ojeda /// 77*c3739801SMiguel Ojeda /// [`deref`]: core::ops::Deref::deref 78*c3739801SMiguel Ojeda /// [`deref_mut`]: core::ops::DerefMut::deref_mut 79*c3739801SMiguel Ojeda /// [`into`]: core::convert::Into::into 80*c3739801SMiguel Ojeda pub(crate) unsafe fn new_unchecked(bytes: B) -> Ref<B, T> { 81*c3739801SMiguel Ojeda // INVARIANTS: The caller has promised that `bytes`'s referent is 82*c3739801SMiguel Ojeda // validly-aligned and has a valid size. 83*c3739801SMiguel Ojeda Ref(bytes, PhantomData) 84*c3739801SMiguel Ojeda } 85*c3739801SMiguel Ojeda } 86*c3739801SMiguel Ojeda 87*c3739801SMiguel Ojeda impl<B: ByteSlice, T: ?Sized> Ref<B, T> { 88*c3739801SMiguel Ojeda /// Access the byte slice as a [`ByteSlice`]. 89*c3739801SMiguel Ojeda /// 90*c3739801SMiguel Ojeda /// # Safety 91*c3739801SMiguel Ojeda /// 92*c3739801SMiguel Ojeda /// The caller promises not to call methods on the returned 93*c3739801SMiguel Ojeda /// [`ByteSlice`] other than `ByteSlice` methods (for example, via 94*c3739801SMiguel Ojeda /// `Any::downcast_ref`). 95*c3739801SMiguel Ojeda /// 96*c3739801SMiguel Ojeda /// `as_byte_slice` promises to return a `ByteSlice` whose referent is 97*c3739801SMiguel Ojeda /// validly-aligned for `T` and has a valid size for `T`. 98*c3739801SMiguel Ojeda pub(crate) unsafe fn as_byte_slice(&self) -> &impl ByteSlice { 99*c3739801SMiguel Ojeda // INVARIANTS: The caller promises not to call methods other than 100*c3739801SMiguel Ojeda // those on `ByteSlice`. Since `B: ByteSlice`, dereference stability 101*c3739801SMiguel Ojeda // guarantees that calling `ByteSlice` methods will not change the 102*c3739801SMiguel Ojeda // address or length of `self.0`'s referent. 103*c3739801SMiguel Ojeda // 104*c3739801SMiguel Ojeda // SAFETY: By invariant on `self.0`, the alignment and size 105*c3739801SMiguel Ojeda // post-conditions are upheld. 106*c3739801SMiguel Ojeda &self.0 107*c3739801SMiguel Ojeda } 108*c3739801SMiguel Ojeda } 109*c3739801SMiguel Ojeda 110*c3739801SMiguel Ojeda impl<B: ByteSliceMut, T: ?Sized> Ref<B, T> { 111*c3739801SMiguel Ojeda /// Access the byte slice as a [`ByteSliceMut`]. 112*c3739801SMiguel Ojeda /// 113*c3739801SMiguel Ojeda /// # Safety 114*c3739801SMiguel Ojeda /// 115*c3739801SMiguel Ojeda /// The caller promises not to call methods on the returned 116*c3739801SMiguel Ojeda /// [`ByteSliceMut`] other than `ByteSliceMut` methods (for example, via 117*c3739801SMiguel Ojeda /// `Any::downcast_mut`). 118*c3739801SMiguel Ojeda /// 119*c3739801SMiguel Ojeda /// `as_byte_slice` promises to return a `ByteSlice` whose referent is 120*c3739801SMiguel Ojeda /// validly-aligned for `T` and has a valid size for `T`. 121*c3739801SMiguel Ojeda pub(crate) unsafe fn as_byte_slice_mut(&mut self) -> &mut impl ByteSliceMut { 122*c3739801SMiguel Ojeda // INVARIANTS: The caller promises not to call methods other than 123*c3739801SMiguel Ojeda // those on `ByteSliceMut`. Since `B: ByteSlice`, dereference 124*c3739801SMiguel Ojeda // stability guarantees that calling `ByteSlice` methods will not 125*c3739801SMiguel Ojeda // change the address or length of `self.0`'s referent. 126*c3739801SMiguel Ojeda // 127*c3739801SMiguel Ojeda // SAFETY: By invariant on `self.0`, the alignment and size 128*c3739801SMiguel Ojeda // post-conditions are upheld. 129*c3739801SMiguel Ojeda &mut self.0 130*c3739801SMiguel Ojeda } 131*c3739801SMiguel Ojeda } 132*c3739801SMiguel Ojeda 133*c3739801SMiguel Ojeda impl<'a, B: IntoByteSlice<'a>, T: ?Sized> Ref<B, T> { 134*c3739801SMiguel Ojeda /// Access the byte slice as an [`IntoByteSlice`]. 135*c3739801SMiguel Ojeda /// 136*c3739801SMiguel Ojeda /// # Safety 137*c3739801SMiguel Ojeda /// 138*c3739801SMiguel Ojeda /// The caller promises not to call methods on the returned 139*c3739801SMiguel Ojeda /// [`IntoByteSlice`] other than `IntoByteSlice` methods (for example, 140*c3739801SMiguel Ojeda /// via `Any::downcast_ref`). 141*c3739801SMiguel Ojeda /// 142*c3739801SMiguel Ojeda /// `as_byte_slice` promises to return a `ByteSlice` whose referent is 143*c3739801SMiguel Ojeda /// validly-aligned for `T` and has a valid size for `T`. 144*c3739801SMiguel Ojeda pub(crate) unsafe fn into_byte_slice(self) -> impl IntoByteSlice<'a> { 145*c3739801SMiguel Ojeda // INVARIANTS: The caller promises not to call methods other than 146*c3739801SMiguel Ojeda // those on `IntoByteSlice`. Since `B: ByteSlice`, dereference 147*c3739801SMiguel Ojeda // stability guarantees that calling `ByteSlice` methods will not 148*c3739801SMiguel Ojeda // change the address or length of `self.0`'s referent. 149*c3739801SMiguel Ojeda // 150*c3739801SMiguel Ojeda // SAFETY: By invariant on `self.0`, the alignment and size 151*c3739801SMiguel Ojeda // post-conditions are upheld. 152*c3739801SMiguel Ojeda self.0 153*c3739801SMiguel Ojeda } 154*c3739801SMiguel Ojeda } 155*c3739801SMiguel Ojeda 156*c3739801SMiguel Ojeda impl<'a, B: IntoByteSliceMut<'a>, T: ?Sized> Ref<B, T> { 157*c3739801SMiguel Ojeda /// Access the byte slice as an [`IntoByteSliceMut`]. 158*c3739801SMiguel Ojeda /// 159*c3739801SMiguel Ojeda /// # Safety 160*c3739801SMiguel Ojeda /// 161*c3739801SMiguel Ojeda /// The caller promises not to call methods on the returned 162*c3739801SMiguel Ojeda /// [`IntoByteSliceMut`] other than `IntoByteSliceMut` methods (for 163*c3739801SMiguel Ojeda /// example, via `Any::downcast_mut`). 164*c3739801SMiguel Ojeda /// 165*c3739801SMiguel Ojeda /// `as_byte_slice` promises to return a `ByteSlice` whose referent is 166*c3739801SMiguel Ojeda /// validly-aligned for `T` and has a valid size for `T`. 167*c3739801SMiguel Ojeda pub(crate) unsafe fn into_byte_slice_mut(self) -> impl IntoByteSliceMut<'a> { 168*c3739801SMiguel Ojeda // INVARIANTS: The caller promises not to call methods other than 169*c3739801SMiguel Ojeda // those on `IntoByteSliceMut`. Since `B: ByteSlice`, dereference 170*c3739801SMiguel Ojeda // stability guarantees that calling `ByteSlice` methods will not 171*c3739801SMiguel Ojeda // change the address or length of `self.0`'s referent. 172*c3739801SMiguel Ojeda // 173*c3739801SMiguel Ojeda // SAFETY: By invariant on `self.0`, the alignment and size 174*c3739801SMiguel Ojeda // post-conditions are upheld. 175*c3739801SMiguel Ojeda self.0 176*c3739801SMiguel Ojeda } 177*c3739801SMiguel Ojeda } 178*c3739801SMiguel Ojeda 179*c3739801SMiguel Ojeda impl<B: CloneableByteSlice + Clone, T: ?Sized> Clone for Ref<B, T> { 180*c3739801SMiguel Ojeda #[inline] 181*c3739801SMiguel Ojeda fn clone(&self) -> Ref<B, T> { 182*c3739801SMiguel Ojeda // INVARIANTS: Since `B: CloneableByteSlice`, `self.0.clone()` has 183*c3739801SMiguel Ojeda // the same address and length as `self.0`. Since `self.0` upholds 184*c3739801SMiguel Ojeda // the field invariants, so does `self.0.clone()`. 185*c3739801SMiguel Ojeda Ref(self.0.clone(), PhantomData) 186*c3739801SMiguel Ojeda } 187*c3739801SMiguel Ojeda } 188*c3739801SMiguel Ojeda 189*c3739801SMiguel Ojeda // INVARIANTS: Since `B: CopyableByteSlice`, the copied `Ref`'s `.0` has the 190*c3739801SMiguel Ojeda // same address and length as the original `Ref`'s `.0`. Since the original 191*c3739801SMiguel Ojeda // upholds the field invariants, so does the copy. 192*c3739801SMiguel Ojeda impl<B: CopyableByteSlice + Copy, T: ?Sized> Copy for Ref<B, T> {} 193*c3739801SMiguel Ojeda } 194*c3739801SMiguel Ojeda 195*c3739801SMiguel Ojeda #[allow(unreachable_pub)] // This is a false positive on our MSRV toolchain. 196*c3739801SMiguel Ojeda pub use def::Ref; 197*c3739801SMiguel Ojeda 198*c3739801SMiguel Ojeda use crate::pointer::{ 199*c3739801SMiguel Ojeda invariant::{Aligned, BecauseExclusive, Initialized, Unaligned, Valid}, 200*c3739801SMiguel Ojeda BecauseRead, PtrInner, 201*c3739801SMiguel Ojeda }; 202*c3739801SMiguel Ojeda 203*c3739801SMiguel Ojeda impl<B, T> Ref<B, T> 204*c3739801SMiguel Ojeda where 205*c3739801SMiguel Ojeda B: ByteSlice, 206*c3739801SMiguel Ojeda { 207*c3739801SMiguel Ojeda #[must_use = "has no side effects"] 208*c3739801SMiguel Ojeda pub(crate) fn sized_from(bytes: B) -> Result<Ref<B, T>, CastError<B, T>> { 209*c3739801SMiguel Ojeda if bytes.len() != mem::size_of::<T>() { 210*c3739801SMiguel Ojeda return Err(SizeError::new(bytes).into()); 211*c3739801SMiguel Ojeda } 212*c3739801SMiguel Ojeda if let Err(err) = util::validate_aligned_to::<_, T>(bytes.deref()) { 213*c3739801SMiguel Ojeda return Err(err.with_src(bytes).into()); 214*c3739801SMiguel Ojeda } 215*c3739801SMiguel Ojeda 216*c3739801SMiguel Ojeda // SAFETY: We just validated size and alignment. 217*c3739801SMiguel Ojeda Ok(unsafe { Ref::new_unchecked(bytes) }) 218*c3739801SMiguel Ojeda } 219*c3739801SMiguel Ojeda } 220*c3739801SMiguel Ojeda 221*c3739801SMiguel Ojeda impl<B, T> Ref<B, T> 222*c3739801SMiguel Ojeda where 223*c3739801SMiguel Ojeda B: SplitByteSlice, 224*c3739801SMiguel Ojeda { 225*c3739801SMiguel Ojeda #[must_use = "has no side effects"] 226*c3739801SMiguel Ojeda pub(crate) fn sized_from_prefix(bytes: B) -> Result<(Ref<B, T>, B), CastError<B, T>> { 227*c3739801SMiguel Ojeda if bytes.len() < mem::size_of::<T>() { 228*c3739801SMiguel Ojeda return Err(SizeError::new(bytes).into()); 229*c3739801SMiguel Ojeda } 230*c3739801SMiguel Ojeda if let Err(err) = util::validate_aligned_to::<_, T>(bytes.deref()) { 231*c3739801SMiguel Ojeda return Err(err.with_src(bytes).into()); 232*c3739801SMiguel Ojeda } 233*c3739801SMiguel Ojeda let (bytes, suffix) = bytes.split_at(mem::size_of::<T>()).map_err( 234*c3739801SMiguel Ojeda #[inline(always)] 235*c3739801SMiguel Ojeda |b| SizeError::new(b).into(), 236*c3739801SMiguel Ojeda )?; 237*c3739801SMiguel Ojeda // SAFETY: We just validated alignment and that `bytes` is at least as 238*c3739801SMiguel Ojeda // large as `T`. `bytes.split_at(mem::size_of::<T>())?` ensures that the 239*c3739801SMiguel Ojeda // new `bytes` is exactly the size of `T`. By safety postcondition on 240*c3739801SMiguel Ojeda // `SplitByteSlice::split_at` we can rely on `split_at` to produce the 241*c3739801SMiguel Ojeda // correct `bytes` and `suffix`. 242*c3739801SMiguel Ojeda let r = unsafe { Ref::new_unchecked(bytes) }; 243*c3739801SMiguel Ojeda Ok((r, suffix)) 244*c3739801SMiguel Ojeda } 245*c3739801SMiguel Ojeda 246*c3739801SMiguel Ojeda #[must_use = "has no side effects"] 247*c3739801SMiguel Ojeda pub(crate) fn sized_from_suffix(bytes: B) -> Result<(B, Ref<B, T>), CastError<B, T>> { 248*c3739801SMiguel Ojeda let bytes_len = bytes.len(); 249*c3739801SMiguel Ojeda let split_at = if let Some(split_at) = bytes_len.checked_sub(mem::size_of::<T>()) { 250*c3739801SMiguel Ojeda split_at 251*c3739801SMiguel Ojeda } else { 252*c3739801SMiguel Ojeda return Err(SizeError::new(bytes).into()); 253*c3739801SMiguel Ojeda }; 254*c3739801SMiguel Ojeda let (prefix, bytes) = bytes.split_at(split_at).map_err(|b| SizeError::new(b).into())?; 255*c3739801SMiguel Ojeda if let Err(err) = util::validate_aligned_to::<_, T>(bytes.deref()) { 256*c3739801SMiguel Ojeda return Err(err.with_src(bytes).into()); 257*c3739801SMiguel Ojeda } 258*c3739801SMiguel Ojeda // SAFETY: Since `split_at` is defined as `bytes_len - size_of::<T>()`, 259*c3739801SMiguel Ojeda // the `bytes` which results from `let (prefix, bytes) = 260*c3739801SMiguel Ojeda // bytes.split_at(split_at)?` has length `size_of::<T>()`. After 261*c3739801SMiguel Ojeda // constructing `bytes`, we validate that it has the proper alignment. 262*c3739801SMiguel Ojeda // By safety postcondition on `SplitByteSlice::split_at` we can rely on 263*c3739801SMiguel Ojeda // `split_at` to produce the correct `prefix` and `bytes`. 264*c3739801SMiguel Ojeda let r = unsafe { Ref::new_unchecked(bytes) }; 265*c3739801SMiguel Ojeda Ok((prefix, r)) 266*c3739801SMiguel Ojeda } 267*c3739801SMiguel Ojeda } 268*c3739801SMiguel Ojeda 269*c3739801SMiguel Ojeda impl<B, T> Ref<B, T> 270*c3739801SMiguel Ojeda where 271*c3739801SMiguel Ojeda B: ByteSlice, 272*c3739801SMiguel Ojeda T: KnownLayout + Immutable + ?Sized, 273*c3739801SMiguel Ojeda { 274*c3739801SMiguel Ojeda /// Constructs a `Ref` from a byte slice. 275*c3739801SMiguel Ojeda /// 276*c3739801SMiguel Ojeda /// If the length of `source` is not a [valid size of `T`][valid-size], or 277*c3739801SMiguel Ojeda /// if `source` is not appropriately aligned for `T`, this returns `Err`. If 278*c3739801SMiguel Ojeda /// [`T: Unaligned`][t-unaligned], you can [infallibly discard the alignment 279*c3739801SMiguel Ojeda /// error][size-error-from]. 280*c3739801SMiguel Ojeda /// 281*c3739801SMiguel Ojeda /// `T` may be a sized type, a slice, or a [slice DST][slice-dst]. 282*c3739801SMiguel Ojeda /// 283*c3739801SMiguel Ojeda /// [valid-size]: crate::KnownLayout#what-is-a-valid-size 284*c3739801SMiguel Ojeda /// [t-unaligned]: crate::Unaligned 285*c3739801SMiguel Ojeda /// [size-error-from]: error/struct.SizeError.html#method.from-1 286*c3739801SMiguel Ojeda /// [slice-dst]: KnownLayout#dynamically-sized-types 287*c3739801SMiguel Ojeda /// 288*c3739801SMiguel Ojeda /// # Compile-Time Assertions 289*c3739801SMiguel Ojeda /// 290*c3739801SMiguel Ojeda /// This method cannot yet be used on unsized types whose dynamically-sized 291*c3739801SMiguel Ojeda /// component is zero-sized. Attempting to use this method on such types 292*c3739801SMiguel Ojeda /// results in a compile-time assertion error; e.g.: 293*c3739801SMiguel Ojeda /// 294*c3739801SMiguel Ojeda /// ```compile_fail,E0080 295*c3739801SMiguel Ojeda /// use zerocopy::*; 296*c3739801SMiguel Ojeda /// # use zerocopy_derive::*; 297*c3739801SMiguel Ojeda /// 298*c3739801SMiguel Ojeda /// #[derive(Immutable, KnownLayout)] 299*c3739801SMiguel Ojeda /// #[repr(C)] 300*c3739801SMiguel Ojeda /// struct ZSTy { 301*c3739801SMiguel Ojeda /// leading_sized: u16, 302*c3739801SMiguel Ojeda /// trailing_dst: [()], 303*c3739801SMiguel Ojeda /// } 304*c3739801SMiguel Ojeda /// 305*c3739801SMiguel Ojeda /// let _ = Ref::<_, ZSTy>::from_bytes(&b"UU"[..]); // ⚠ Compile Error! 306*c3739801SMiguel Ojeda /// ``` 307*c3739801SMiguel Ojeda #[must_use = "has no side effects"] 308*c3739801SMiguel Ojeda #[inline] 309*c3739801SMiguel Ojeda pub fn from_bytes(source: B) -> Result<Ref<B, T>, CastError<B, T>> { 310*c3739801SMiguel Ojeda static_assert_dst_is_not_zst!(T); 311*c3739801SMiguel Ojeda if let Err(e) = 312*c3739801SMiguel Ojeda Ptr::from_ref(source.deref()).try_cast_into_no_leftover::<T, BecauseImmutable>(None) 313*c3739801SMiguel Ojeda { 314*c3739801SMiguel Ojeda return Err(e.with_src(()).with_src(source)); 315*c3739801SMiguel Ojeda } 316*c3739801SMiguel Ojeda // SAFETY: `try_cast_into_no_leftover` validates size and alignment. 317*c3739801SMiguel Ojeda Ok(unsafe { Ref::new_unchecked(source) }) 318*c3739801SMiguel Ojeda } 319*c3739801SMiguel Ojeda } 320*c3739801SMiguel Ojeda 321*c3739801SMiguel Ojeda impl<B, T> Ref<B, T> 322*c3739801SMiguel Ojeda where 323*c3739801SMiguel Ojeda B: SplitByteSlice, 324*c3739801SMiguel Ojeda T: KnownLayout + Immutable + ?Sized, 325*c3739801SMiguel Ojeda { 326*c3739801SMiguel Ojeda /// Constructs a `Ref` from the prefix of a byte slice. 327*c3739801SMiguel Ojeda /// 328*c3739801SMiguel Ojeda /// This method computes the [largest possible size of `T`][valid-size] that 329*c3739801SMiguel Ojeda /// can fit in the leading bytes of `source`, then attempts to return both a 330*c3739801SMiguel Ojeda /// `Ref` to those bytes, and a reference to the remaining bytes. If there 331*c3739801SMiguel Ojeda /// are insufficient bytes, or if `source` is not appropriately aligned, 332*c3739801SMiguel Ojeda /// this returns `Err`. If [`T: Unaligned`][t-unaligned], you can 333*c3739801SMiguel Ojeda /// [infallibly discard the alignment error][size-error-from]. 334*c3739801SMiguel Ojeda /// 335*c3739801SMiguel Ojeda /// `T` may be a sized type, a slice, or a [slice DST][slice-dst]. 336*c3739801SMiguel Ojeda /// 337*c3739801SMiguel Ojeda /// [valid-size]: crate::KnownLayout#what-is-a-valid-size 338*c3739801SMiguel Ojeda /// [t-unaligned]: crate::Unaligned 339*c3739801SMiguel Ojeda /// [size-error-from]: error/struct.SizeError.html#method.from-1 340*c3739801SMiguel Ojeda /// [slice-dst]: KnownLayout#dynamically-sized-types 341*c3739801SMiguel Ojeda /// 342*c3739801SMiguel Ojeda /// # Compile-Time Assertions 343*c3739801SMiguel Ojeda /// 344*c3739801SMiguel Ojeda /// This method cannot yet be used on unsized types whose dynamically-sized 345*c3739801SMiguel Ojeda /// component is zero-sized. Attempting to use this method on such types 346*c3739801SMiguel Ojeda /// results in a compile-time assertion error; e.g.: 347*c3739801SMiguel Ojeda /// 348*c3739801SMiguel Ojeda /// ```compile_fail,E0080 349*c3739801SMiguel Ojeda /// use zerocopy::*; 350*c3739801SMiguel Ojeda /// # use zerocopy_derive::*; 351*c3739801SMiguel Ojeda /// 352*c3739801SMiguel Ojeda /// #[derive(Immutable, KnownLayout)] 353*c3739801SMiguel Ojeda /// #[repr(C)] 354*c3739801SMiguel Ojeda /// struct ZSTy { 355*c3739801SMiguel Ojeda /// leading_sized: u16, 356*c3739801SMiguel Ojeda /// trailing_dst: [()], 357*c3739801SMiguel Ojeda /// } 358*c3739801SMiguel Ojeda /// 359*c3739801SMiguel Ojeda /// let _ = Ref::<_, ZSTy>::from_prefix(&b"UU"[..]); // ⚠ Compile Error! 360*c3739801SMiguel Ojeda /// ``` 361*c3739801SMiguel Ojeda #[must_use = "has no side effects"] 362*c3739801SMiguel Ojeda #[inline] 363*c3739801SMiguel Ojeda pub fn from_prefix(source: B) -> Result<(Ref<B, T>, B), CastError<B, T>> { 364*c3739801SMiguel Ojeda static_assert_dst_is_not_zst!(T); 365*c3739801SMiguel Ojeda let remainder = match Ptr::from_ref(source.deref()) 366*c3739801SMiguel Ojeda .try_cast_into::<T, BecauseImmutable>(CastType::Prefix, None) 367*c3739801SMiguel Ojeda { 368*c3739801SMiguel Ojeda Ok((_, remainder)) => remainder, 369*c3739801SMiguel Ojeda Err(e) => { 370*c3739801SMiguel Ojeda return Err(e.with_src(()).with_src(source)); 371*c3739801SMiguel Ojeda } 372*c3739801SMiguel Ojeda }; 373*c3739801SMiguel Ojeda 374*c3739801SMiguel Ojeda // SAFETY: `remainder` is constructed as a subset of `source`, and so it 375*c3739801SMiguel Ojeda // cannot have a larger size than `source`. Both of their `len` methods 376*c3739801SMiguel Ojeda // measure bytes (`source` deref's to `[u8]`, and `remainder` is a 377*c3739801SMiguel Ojeda // `Ptr<[u8]>`), so `source.len() >= remainder.len()`. Thus, this cannot 378*c3739801SMiguel Ojeda // underflow. 379*c3739801SMiguel Ojeda #[allow(unstable_name_collisions)] 380*c3739801SMiguel Ojeda let split_at = unsafe { source.len().unchecked_sub(remainder.len()) }; 381*c3739801SMiguel Ojeda let (bytes, suffix) = source.split_at(split_at).map_err(|b| SizeError::new(b).into())?; 382*c3739801SMiguel Ojeda // SAFETY: `try_cast_into` validates size and alignment, and returns a 383*c3739801SMiguel Ojeda // `split_at` that indicates how many bytes of `source` correspond to a 384*c3739801SMiguel Ojeda // valid `T`. By safety postcondition on `SplitByteSlice::split_at` we 385*c3739801SMiguel Ojeda // can rely on `split_at` to produce the correct `source` and `suffix`. 386*c3739801SMiguel Ojeda let r = unsafe { Ref::new_unchecked(bytes) }; 387*c3739801SMiguel Ojeda Ok((r, suffix)) 388*c3739801SMiguel Ojeda } 389*c3739801SMiguel Ojeda 390*c3739801SMiguel Ojeda /// Constructs a `Ref` from the suffix of a byte slice. 391*c3739801SMiguel Ojeda /// 392*c3739801SMiguel Ojeda /// This method computes the [largest possible size of `T`][valid-size] that 393*c3739801SMiguel Ojeda /// can fit in the trailing bytes of `source`, then attempts to return both 394*c3739801SMiguel Ojeda /// a `Ref` to those bytes, and a reference to the preceding bytes. If there 395*c3739801SMiguel Ojeda /// are insufficient bytes, or if that suffix of `source` is not 396*c3739801SMiguel Ojeda /// appropriately aligned, this returns `Err`. If [`T: 397*c3739801SMiguel Ojeda /// Unaligned`][t-unaligned], you can [infallibly discard the alignment 398*c3739801SMiguel Ojeda /// error][size-error-from]. 399*c3739801SMiguel Ojeda /// 400*c3739801SMiguel Ojeda /// `T` may be a sized type, a slice, or a [slice DST][slice-dst]. 401*c3739801SMiguel Ojeda /// 402*c3739801SMiguel Ojeda /// [valid-size]: crate::KnownLayout#what-is-a-valid-size 403*c3739801SMiguel Ojeda /// [t-unaligned]: crate::Unaligned 404*c3739801SMiguel Ojeda /// [size-error-from]: error/struct.SizeError.html#method.from-1 405*c3739801SMiguel Ojeda /// [slice-dst]: KnownLayout#dynamically-sized-types 406*c3739801SMiguel Ojeda /// 407*c3739801SMiguel Ojeda /// # Compile-Time Assertions 408*c3739801SMiguel Ojeda /// 409*c3739801SMiguel Ojeda /// This method cannot yet be used on unsized types whose dynamically-sized 410*c3739801SMiguel Ojeda /// component is zero-sized. Attempting to use this method on such types 411*c3739801SMiguel Ojeda /// results in a compile-time assertion error; e.g.: 412*c3739801SMiguel Ojeda /// 413*c3739801SMiguel Ojeda /// ```compile_fail,E0080 414*c3739801SMiguel Ojeda /// use zerocopy::*; 415*c3739801SMiguel Ojeda /// # use zerocopy_derive::*; 416*c3739801SMiguel Ojeda /// 417*c3739801SMiguel Ojeda /// #[derive(Immutable, KnownLayout)] 418*c3739801SMiguel Ojeda /// #[repr(C)] 419*c3739801SMiguel Ojeda /// struct ZSTy { 420*c3739801SMiguel Ojeda /// leading_sized: u16, 421*c3739801SMiguel Ojeda /// trailing_dst: [()], 422*c3739801SMiguel Ojeda /// } 423*c3739801SMiguel Ojeda /// 424*c3739801SMiguel Ojeda /// let _ = Ref::<_, ZSTy>::from_suffix(&b"UU"[..]); // ⚠ Compile Error! 425*c3739801SMiguel Ojeda /// ``` 426*c3739801SMiguel Ojeda #[must_use = "has no side effects"] 427*c3739801SMiguel Ojeda #[inline] 428*c3739801SMiguel Ojeda pub fn from_suffix(source: B) -> Result<(B, Ref<B, T>), CastError<B, T>> { 429*c3739801SMiguel Ojeda static_assert_dst_is_not_zst!(T); 430*c3739801SMiguel Ojeda let remainder = match Ptr::from_ref(source.deref()) 431*c3739801SMiguel Ojeda .try_cast_into::<T, BecauseImmutable>(CastType::Suffix, None) 432*c3739801SMiguel Ojeda { 433*c3739801SMiguel Ojeda Ok((_, remainder)) => remainder, 434*c3739801SMiguel Ojeda Err(e) => { 435*c3739801SMiguel Ojeda let e = e.with_src(()); 436*c3739801SMiguel Ojeda return Err(e.with_src(source)); 437*c3739801SMiguel Ojeda } 438*c3739801SMiguel Ojeda }; 439*c3739801SMiguel Ojeda 440*c3739801SMiguel Ojeda let split_at = remainder.len(); 441*c3739801SMiguel Ojeda let (prefix, bytes) = source.split_at(split_at).map_err(|b| SizeError::new(b).into())?; 442*c3739801SMiguel Ojeda // SAFETY: `try_cast_into` validates size and alignment, and returns a 443*c3739801SMiguel Ojeda // `split_at` that indicates how many bytes of `source` correspond to a 444*c3739801SMiguel Ojeda // valid `T`. By safety postcondition on `SplitByteSlice::split_at` we 445*c3739801SMiguel Ojeda // can rely on `split_at` to produce the correct `prefix` and `bytes`. 446*c3739801SMiguel Ojeda let r = unsafe { Ref::new_unchecked(bytes) }; 447*c3739801SMiguel Ojeda Ok((prefix, r)) 448*c3739801SMiguel Ojeda } 449*c3739801SMiguel Ojeda } 450*c3739801SMiguel Ojeda 451*c3739801SMiguel Ojeda impl<B, T> Ref<B, T> 452*c3739801SMiguel Ojeda where 453*c3739801SMiguel Ojeda B: ByteSlice, 454*c3739801SMiguel Ojeda T: KnownLayout<PointerMetadata = usize> + Immutable + ?Sized, 455*c3739801SMiguel Ojeda { 456*c3739801SMiguel Ojeda /// Constructs a `Ref` from the given bytes with DST length equal to `count` 457*c3739801SMiguel Ojeda /// without copying. 458*c3739801SMiguel Ojeda /// 459*c3739801SMiguel Ojeda /// This method attempts to return a `Ref` to the prefix of `source` 460*c3739801SMiguel Ojeda /// interpreted as a `T` with `count` trailing elements, and a reference to 461*c3739801SMiguel Ojeda /// the remaining bytes. If the length of `source` is not equal to the size 462*c3739801SMiguel Ojeda /// of `Self` with `count` elements, or if `source` is not appropriately 463*c3739801SMiguel Ojeda /// aligned, this returns `Err`. If [`T: Unaligned`][t-unaligned], you can 464*c3739801SMiguel Ojeda /// [infallibly discard the alignment error][size-error-from]. 465*c3739801SMiguel Ojeda /// 466*c3739801SMiguel Ojeda /// [t-unaligned]: crate::Unaligned 467*c3739801SMiguel Ojeda /// [size-error-from]: error/struct.SizeError.html#method.from-1 468*c3739801SMiguel Ojeda /// 469*c3739801SMiguel Ojeda /// # Compile-Time Assertions 470*c3739801SMiguel Ojeda /// 471*c3739801SMiguel Ojeda /// This method cannot yet be used on unsized types whose dynamically-sized 472*c3739801SMiguel Ojeda /// component is zero-sized. Attempting to use this method on such types 473*c3739801SMiguel Ojeda /// results in a compile-time assertion error; e.g.: 474*c3739801SMiguel Ojeda /// 475*c3739801SMiguel Ojeda /// ```compile_fail,E0080 476*c3739801SMiguel Ojeda /// use zerocopy::*; 477*c3739801SMiguel Ojeda /// # use zerocopy_derive::*; 478*c3739801SMiguel Ojeda /// 479*c3739801SMiguel Ojeda /// #[derive(Immutable, KnownLayout)] 480*c3739801SMiguel Ojeda /// #[repr(C)] 481*c3739801SMiguel Ojeda /// struct ZSTy { 482*c3739801SMiguel Ojeda /// leading_sized: u16, 483*c3739801SMiguel Ojeda /// trailing_dst: [()], 484*c3739801SMiguel Ojeda /// } 485*c3739801SMiguel Ojeda /// 486*c3739801SMiguel Ojeda /// let _ = Ref::<_, ZSTy>::from_bytes_with_elems(&b"UU"[..], 42); // ⚠ Compile Error! 487*c3739801SMiguel Ojeda /// ``` 488*c3739801SMiguel Ojeda #[inline] 489*c3739801SMiguel Ojeda pub fn from_bytes_with_elems(source: B, count: usize) -> Result<Ref<B, T>, CastError<B, T>> { 490*c3739801SMiguel Ojeda static_assert_dst_is_not_zst!(T); 491*c3739801SMiguel Ojeda let expected_len = match T::size_for_metadata(count) { 492*c3739801SMiguel Ojeda Some(len) => len, 493*c3739801SMiguel Ojeda None => return Err(SizeError::new(source).into()), 494*c3739801SMiguel Ojeda }; 495*c3739801SMiguel Ojeda if source.len() != expected_len { 496*c3739801SMiguel Ojeda return Err(SizeError::new(source).into()); 497*c3739801SMiguel Ojeda } 498*c3739801SMiguel Ojeda Self::from_bytes(source) 499*c3739801SMiguel Ojeda } 500*c3739801SMiguel Ojeda } 501*c3739801SMiguel Ojeda 502*c3739801SMiguel Ojeda impl<B, T> Ref<B, T> 503*c3739801SMiguel Ojeda where 504*c3739801SMiguel Ojeda B: SplitByteSlice, 505*c3739801SMiguel Ojeda T: KnownLayout<PointerMetadata = usize> + Immutable + ?Sized, 506*c3739801SMiguel Ojeda { 507*c3739801SMiguel Ojeda /// Constructs a `Ref` from the prefix of the given bytes with DST 508*c3739801SMiguel Ojeda /// length equal to `count` without copying. 509*c3739801SMiguel Ojeda /// 510*c3739801SMiguel Ojeda /// This method attempts to return a `Ref` to the prefix of `source` 511*c3739801SMiguel Ojeda /// interpreted as a `T` with `count` trailing elements, and a reference to 512*c3739801SMiguel Ojeda /// the remaining bytes. If there are insufficient bytes, or if `source` is 513*c3739801SMiguel Ojeda /// not appropriately aligned, this returns `Err`. If [`T: 514*c3739801SMiguel Ojeda /// Unaligned`][t-unaligned], you can [infallibly discard the alignment 515*c3739801SMiguel Ojeda /// error][size-error-from]. 516*c3739801SMiguel Ojeda /// 517*c3739801SMiguel Ojeda /// [t-unaligned]: crate::Unaligned 518*c3739801SMiguel Ojeda /// [size-error-from]: error/struct.SizeError.html#method.from-1 519*c3739801SMiguel Ojeda /// 520*c3739801SMiguel Ojeda /// # Compile-Time Assertions 521*c3739801SMiguel Ojeda /// 522*c3739801SMiguel Ojeda /// This method cannot yet be used on unsized types whose dynamically-sized 523*c3739801SMiguel Ojeda /// component is zero-sized. Attempting to use this method on such types 524*c3739801SMiguel Ojeda /// results in a compile-time assertion error; e.g.: 525*c3739801SMiguel Ojeda /// 526*c3739801SMiguel Ojeda /// ```compile_fail,E0080 527*c3739801SMiguel Ojeda /// use zerocopy::*; 528*c3739801SMiguel Ojeda /// # use zerocopy_derive::*; 529*c3739801SMiguel Ojeda /// 530*c3739801SMiguel Ojeda /// #[derive(Immutable, KnownLayout)] 531*c3739801SMiguel Ojeda /// #[repr(C)] 532*c3739801SMiguel Ojeda /// struct ZSTy { 533*c3739801SMiguel Ojeda /// leading_sized: u16, 534*c3739801SMiguel Ojeda /// trailing_dst: [()], 535*c3739801SMiguel Ojeda /// } 536*c3739801SMiguel Ojeda /// 537*c3739801SMiguel Ojeda /// let _ = Ref::<_, ZSTy>::from_prefix_with_elems(&b"UU"[..], 42); // ⚠ Compile Error! 538*c3739801SMiguel Ojeda /// ``` 539*c3739801SMiguel Ojeda #[inline] 540*c3739801SMiguel Ojeda pub fn from_prefix_with_elems( 541*c3739801SMiguel Ojeda source: B, 542*c3739801SMiguel Ojeda count: usize, 543*c3739801SMiguel Ojeda ) -> Result<(Ref<B, T>, B), CastError<B, T>> { 544*c3739801SMiguel Ojeda static_assert_dst_is_not_zst!(T); 545*c3739801SMiguel Ojeda let expected_len = match T::size_for_metadata(count) { 546*c3739801SMiguel Ojeda Some(len) => len, 547*c3739801SMiguel Ojeda None => return Err(SizeError::new(source).into()), 548*c3739801SMiguel Ojeda }; 549*c3739801SMiguel Ojeda let (prefix, bytes) = source.split_at(expected_len).map_err(SizeError::new)?; 550*c3739801SMiguel Ojeda Self::from_bytes(prefix).map(move |l| (l, bytes)) 551*c3739801SMiguel Ojeda } 552*c3739801SMiguel Ojeda 553*c3739801SMiguel Ojeda /// Constructs a `Ref` from the suffix of the given bytes with DST length 554*c3739801SMiguel Ojeda /// equal to `count` without copying. 555*c3739801SMiguel Ojeda /// 556*c3739801SMiguel Ojeda /// This method attempts to return a `Ref` to the suffix of `source` 557*c3739801SMiguel Ojeda /// interpreted as a `T` with `count` trailing elements, and a reference to 558*c3739801SMiguel Ojeda /// the preceding bytes. If there are insufficient bytes, or if that suffix 559*c3739801SMiguel Ojeda /// of `source` is not appropriately aligned, this returns `Err`. If [`T: 560*c3739801SMiguel Ojeda /// Unaligned`][t-unaligned], you can [infallibly discard the alignment 561*c3739801SMiguel Ojeda /// error][size-error-from]. 562*c3739801SMiguel Ojeda /// 563*c3739801SMiguel Ojeda /// [t-unaligned]: crate::Unaligned 564*c3739801SMiguel Ojeda /// [size-error-from]: error/struct.SizeError.html#method.from-1 565*c3739801SMiguel Ojeda /// 566*c3739801SMiguel Ojeda /// # Compile-Time Assertions 567*c3739801SMiguel Ojeda /// 568*c3739801SMiguel Ojeda /// This method cannot yet be used on unsized types whose dynamically-sized 569*c3739801SMiguel Ojeda /// component is zero-sized. Attempting to use this method on such types 570*c3739801SMiguel Ojeda /// results in a compile-time assertion error; e.g.: 571*c3739801SMiguel Ojeda /// 572*c3739801SMiguel Ojeda /// ```compile_fail,E0080 573*c3739801SMiguel Ojeda /// use zerocopy::*; 574*c3739801SMiguel Ojeda /// # use zerocopy_derive::*; 575*c3739801SMiguel Ojeda /// 576*c3739801SMiguel Ojeda /// #[derive(Immutable, KnownLayout)] 577*c3739801SMiguel Ojeda /// #[repr(C)] 578*c3739801SMiguel Ojeda /// struct ZSTy { 579*c3739801SMiguel Ojeda /// leading_sized: u16, 580*c3739801SMiguel Ojeda /// trailing_dst: [()], 581*c3739801SMiguel Ojeda /// } 582*c3739801SMiguel Ojeda /// 583*c3739801SMiguel Ojeda /// let _ = Ref::<_, ZSTy>::from_suffix_with_elems(&b"UU"[..], 42); // ⚠ Compile Error! 584*c3739801SMiguel Ojeda /// ``` 585*c3739801SMiguel Ojeda #[inline] 586*c3739801SMiguel Ojeda pub fn from_suffix_with_elems( 587*c3739801SMiguel Ojeda source: B, 588*c3739801SMiguel Ojeda count: usize, 589*c3739801SMiguel Ojeda ) -> Result<(B, Ref<B, T>), CastError<B, T>> { 590*c3739801SMiguel Ojeda static_assert_dst_is_not_zst!(T); 591*c3739801SMiguel Ojeda let expected_len = match T::size_for_metadata(count) { 592*c3739801SMiguel Ojeda Some(len) => len, 593*c3739801SMiguel Ojeda None => return Err(SizeError::new(source).into()), 594*c3739801SMiguel Ojeda }; 595*c3739801SMiguel Ojeda let split_at = if let Some(split_at) = source.len().checked_sub(expected_len) { 596*c3739801SMiguel Ojeda split_at 597*c3739801SMiguel Ojeda } else { 598*c3739801SMiguel Ojeda return Err(SizeError::new(source).into()); 599*c3739801SMiguel Ojeda }; 600*c3739801SMiguel Ojeda // SAFETY: The preceding `source.len().checked_sub(expected_len)` 601*c3739801SMiguel Ojeda // guarantees that `split_at` is in-bounds. 602*c3739801SMiguel Ojeda let (bytes, suffix) = unsafe { source.split_at_unchecked(split_at) }; 603*c3739801SMiguel Ojeda Self::from_bytes(suffix).map(move |l| (bytes, l)) 604*c3739801SMiguel Ojeda } 605*c3739801SMiguel Ojeda } 606*c3739801SMiguel Ojeda 607*c3739801SMiguel Ojeda impl<'a, B, T> Ref<B, T> 608*c3739801SMiguel Ojeda where 609*c3739801SMiguel Ojeda B: 'a + IntoByteSlice<'a>, 610*c3739801SMiguel Ojeda T: FromBytes + KnownLayout + Immutable + ?Sized, 611*c3739801SMiguel Ojeda { 612*c3739801SMiguel Ojeda /// Converts this `Ref` into a reference. 613*c3739801SMiguel Ojeda /// 614*c3739801SMiguel Ojeda /// `into_ref` consumes the `Ref`, and returns a reference to `T`. 615*c3739801SMiguel Ojeda /// 616*c3739801SMiguel Ojeda /// Note: this is an associated function, which means that you have to call 617*c3739801SMiguel Ojeda /// it as `Ref::into_ref(r)` instead of `r.into_ref()`. This is so that 618*c3739801SMiguel Ojeda /// there is no conflict with a method on the inner type. 619*c3739801SMiguel Ojeda #[must_use = "has no side effects"] 620*c3739801SMiguel Ojeda #[inline(always)] 621*c3739801SMiguel Ojeda pub fn into_ref(r: Self) -> &'a T { 622*c3739801SMiguel Ojeda // Presumably unreachable, since we've guarded each constructor of `Ref`. 623*c3739801SMiguel Ojeda static_assert_dst_is_not_zst!(T); 624*c3739801SMiguel Ojeda 625*c3739801SMiguel Ojeda // SAFETY: We don't call any methods on `b` other than those provided by 626*c3739801SMiguel Ojeda // `IntoByteSlice`. 627*c3739801SMiguel Ojeda let b = unsafe { r.into_byte_slice() }; 628*c3739801SMiguel Ojeda let b = b.into_byte_slice(); 629*c3739801SMiguel Ojeda 630*c3739801SMiguel Ojeda if let crate::layout::SizeInfo::Sized { .. } = T::LAYOUT.size_info { 631*c3739801SMiguel Ojeda let ptr = Ptr::from_ref(b); 632*c3739801SMiguel Ojeda // SAFETY: We just checked that `T: Sized`. By invariant on `r`, 633*c3739801SMiguel Ojeda // `b`'s size is equal to `size_of::<T>()`. 634*c3739801SMiguel Ojeda let ptr = unsafe { cast_for_sized::<T, _, _, _>(ptr) }; 635*c3739801SMiguel Ojeda 636*c3739801SMiguel Ojeda // SAFETY: None of the preceding transformations modifies the 637*c3739801SMiguel Ojeda // address of the pointer, and by invariant on `r`, we know that it 638*c3739801SMiguel Ojeda // is validly-aligned. 639*c3739801SMiguel Ojeda let ptr = unsafe { ptr.assume_alignment::<Aligned>() }; 640*c3739801SMiguel Ojeda return ptr.as_ref(); 641*c3739801SMiguel Ojeda } 642*c3739801SMiguel Ojeda 643*c3739801SMiguel Ojeda // PANICS: By post-condition on `into_byte_slice`, `b`'s size and 644*c3739801SMiguel Ojeda // alignment are valid for `T`. By post-condition, `b.into_byte_slice()` 645*c3739801SMiguel Ojeda // produces a byte slice with identical address and length to that 646*c3739801SMiguel Ojeda // produced by `b.deref()`. 647*c3739801SMiguel Ojeda let ptr = Ptr::from_ref(b.into_byte_slice()) 648*c3739801SMiguel Ojeda .try_cast_into_no_leftover::<T, BecauseImmutable>(None) 649*c3739801SMiguel Ojeda .expect("zerocopy internal error: into_ref should be infallible"); 650*c3739801SMiguel Ojeda let ptr = ptr.recall_validity(); 651*c3739801SMiguel Ojeda ptr.as_ref() 652*c3739801SMiguel Ojeda } 653*c3739801SMiguel Ojeda } 654*c3739801SMiguel Ojeda 655*c3739801SMiguel Ojeda impl<'a, B, T> Ref<B, T> 656*c3739801SMiguel Ojeda where 657*c3739801SMiguel Ojeda B: 'a + IntoByteSliceMut<'a>, 658*c3739801SMiguel Ojeda T: FromBytes + IntoBytes + KnownLayout + ?Sized, 659*c3739801SMiguel Ojeda { 660*c3739801SMiguel Ojeda /// Converts this `Ref` into a mutable reference. 661*c3739801SMiguel Ojeda /// 662*c3739801SMiguel Ojeda /// `into_mut` consumes the `Ref`, and returns a mutable reference to `T`. 663*c3739801SMiguel Ojeda /// 664*c3739801SMiguel Ojeda /// Note: this is an associated function, which means that you have to call 665*c3739801SMiguel Ojeda /// it as `Ref::into_mut(r)` instead of `r.into_mut()`. This is so that 666*c3739801SMiguel Ojeda /// there is no conflict with a method on the inner type. 667*c3739801SMiguel Ojeda #[must_use = "has no side effects"] 668*c3739801SMiguel Ojeda #[inline(always)] 669*c3739801SMiguel Ojeda pub fn into_mut(r: Self) -> &'a mut T { 670*c3739801SMiguel Ojeda // Presumably unreachable, since we've guarded each constructor of `Ref`. 671*c3739801SMiguel Ojeda static_assert_dst_is_not_zst!(T); 672*c3739801SMiguel Ojeda 673*c3739801SMiguel Ojeda // SAFETY: We don't call any methods on `b` other than those provided by 674*c3739801SMiguel Ojeda // `IntoByteSliceMut`. 675*c3739801SMiguel Ojeda let b = unsafe { r.into_byte_slice_mut() }; 676*c3739801SMiguel Ojeda let b = b.into_byte_slice_mut(); 677*c3739801SMiguel Ojeda 678*c3739801SMiguel Ojeda if let crate::layout::SizeInfo::Sized { .. } = T::LAYOUT.size_info { 679*c3739801SMiguel Ojeda let ptr = Ptr::from_mut(b); 680*c3739801SMiguel Ojeda // SAFETY: We just checked that `T: Sized`. By invariant on `r`, 681*c3739801SMiguel Ojeda // `b`'s size is equal to `size_of::<T>()`. 682*c3739801SMiguel Ojeda let ptr = unsafe { 683*c3739801SMiguel Ojeda cast_for_sized::< 684*c3739801SMiguel Ojeda T, 685*c3739801SMiguel Ojeda _, 686*c3739801SMiguel Ojeda (BecauseRead, BecauseExclusive), 687*c3739801SMiguel Ojeda (BecauseMutationCompatible, BecauseInvariantsEq), 688*c3739801SMiguel Ojeda >(ptr) 689*c3739801SMiguel Ojeda }; 690*c3739801SMiguel Ojeda 691*c3739801SMiguel Ojeda // SAFETY: None of the preceding transformations modifies the 692*c3739801SMiguel Ojeda // address of the pointer, and by invariant on `r`, we know that it 693*c3739801SMiguel Ojeda // is validly-aligned. 694*c3739801SMiguel Ojeda let ptr = unsafe { ptr.assume_alignment::<Aligned>() }; 695*c3739801SMiguel Ojeda return ptr.as_mut(); 696*c3739801SMiguel Ojeda } 697*c3739801SMiguel Ojeda 698*c3739801SMiguel Ojeda // PANICS: By post-condition on `into_byte_slice_mut`, `b`'s size and 699*c3739801SMiguel Ojeda // alignment are valid for `T`. By post-condition, 700*c3739801SMiguel Ojeda // `b.into_byte_slice_mut()` produces a byte slice with identical 701*c3739801SMiguel Ojeda // address and length to that produced by `b.deref_mut()`. 702*c3739801SMiguel Ojeda let ptr = Ptr::from_mut(b.into_byte_slice_mut()) 703*c3739801SMiguel Ojeda .try_cast_into_no_leftover::<T, BecauseExclusive>(None) 704*c3739801SMiguel Ojeda .expect("zerocopy internal error: into_ref should be infallible"); 705*c3739801SMiguel Ojeda let ptr = ptr.recall_validity::<_, (_, (_, _))>(); 706*c3739801SMiguel Ojeda ptr.as_mut() 707*c3739801SMiguel Ojeda } 708*c3739801SMiguel Ojeda } 709*c3739801SMiguel Ojeda 710*c3739801SMiguel Ojeda impl<B, T> Ref<B, T> 711*c3739801SMiguel Ojeda where 712*c3739801SMiguel Ojeda B: ByteSlice, 713*c3739801SMiguel Ojeda T: ?Sized, 714*c3739801SMiguel Ojeda { 715*c3739801SMiguel Ojeda /// Gets the underlying bytes. 716*c3739801SMiguel Ojeda /// 717*c3739801SMiguel Ojeda /// Note: this is an associated function, which means that you have to call 718*c3739801SMiguel Ojeda /// it as `Ref::bytes(r)` instead of `r.bytes()`. This is so that there is 719*c3739801SMiguel Ojeda /// no conflict with a method on the inner type. 720*c3739801SMiguel Ojeda #[inline] 721*c3739801SMiguel Ojeda pub fn bytes(r: &Self) -> &[u8] { 722*c3739801SMiguel Ojeda // SAFETY: We don't call any methods on `b` other than those provided by 723*c3739801SMiguel Ojeda // `ByteSlice`. 724*c3739801SMiguel Ojeda unsafe { r.as_byte_slice().deref() } 725*c3739801SMiguel Ojeda } 726*c3739801SMiguel Ojeda } 727*c3739801SMiguel Ojeda 728*c3739801SMiguel Ojeda impl<B, T> Ref<B, T> 729*c3739801SMiguel Ojeda where 730*c3739801SMiguel Ojeda B: ByteSliceMut, 731*c3739801SMiguel Ojeda T: ?Sized, 732*c3739801SMiguel Ojeda { 733*c3739801SMiguel Ojeda /// Gets the underlying bytes mutably. 734*c3739801SMiguel Ojeda /// 735*c3739801SMiguel Ojeda /// Note: this is an associated function, which means that you have to call 736*c3739801SMiguel Ojeda /// it as `Ref::bytes_mut(r)` instead of `r.bytes_mut()`. This is so that 737*c3739801SMiguel Ojeda /// there is no conflict with a method on the inner type. 738*c3739801SMiguel Ojeda #[inline] 739*c3739801SMiguel Ojeda pub fn bytes_mut(r: &mut Self) -> &mut [u8] { 740*c3739801SMiguel Ojeda // SAFETY: We don't call any methods on `b` other than those provided by 741*c3739801SMiguel Ojeda // `ByteSliceMut`. 742*c3739801SMiguel Ojeda unsafe { r.as_byte_slice_mut().deref_mut() } 743*c3739801SMiguel Ojeda } 744*c3739801SMiguel Ojeda } 745*c3739801SMiguel Ojeda 746*c3739801SMiguel Ojeda impl<B, T> Ref<B, T> 747*c3739801SMiguel Ojeda where 748*c3739801SMiguel Ojeda B: ByteSlice, 749*c3739801SMiguel Ojeda T: FromBytes, 750*c3739801SMiguel Ojeda { 751*c3739801SMiguel Ojeda /// Reads a copy of `T`. 752*c3739801SMiguel Ojeda /// 753*c3739801SMiguel Ojeda /// Note: this is an associated function, which means that you have to call 754*c3739801SMiguel Ojeda /// it as `Ref::read(r)` instead of `r.read()`. This is so that there is no 755*c3739801SMiguel Ojeda /// conflict with a method on the inner type. 756*c3739801SMiguel Ojeda #[must_use = "has no side effects"] 757*c3739801SMiguel Ojeda #[inline] 758*c3739801SMiguel Ojeda pub fn read(r: &Self) -> T { 759*c3739801SMiguel Ojeda // SAFETY: We don't call any methods on `b` other than those provided by 760*c3739801SMiguel Ojeda // `ByteSlice`. 761*c3739801SMiguel Ojeda let b = unsafe { r.as_byte_slice() }; 762*c3739801SMiguel Ojeda 763*c3739801SMiguel Ojeda // SAFETY: By postcondition on `as_byte_slice`, we know that `b` is a 764*c3739801SMiguel Ojeda // valid size and alignment for `T`. By safety invariant on `ByteSlice`, 765*c3739801SMiguel Ojeda // we know that this is preserved via `.deref()`. Because `T: 766*c3739801SMiguel Ojeda // FromBytes`, it is sound to interpret these bytes as a `T`. 767*c3739801SMiguel Ojeda unsafe { ptr::read(b.deref().as_ptr().cast::<T>()) } 768*c3739801SMiguel Ojeda } 769*c3739801SMiguel Ojeda } 770*c3739801SMiguel Ojeda 771*c3739801SMiguel Ojeda impl<B, T> Ref<B, T> 772*c3739801SMiguel Ojeda where 773*c3739801SMiguel Ojeda B: ByteSliceMut, 774*c3739801SMiguel Ojeda T: IntoBytes, 775*c3739801SMiguel Ojeda { 776*c3739801SMiguel Ojeda /// Writes the bytes of `t` and then forgets `t`. 777*c3739801SMiguel Ojeda /// 778*c3739801SMiguel Ojeda /// Note: this is an associated function, which means that you have to call 779*c3739801SMiguel Ojeda /// it as `Ref::write(r, t)` instead of `r.write(t)`. This is so that there 780*c3739801SMiguel Ojeda /// is no conflict with a method on the inner type. 781*c3739801SMiguel Ojeda #[inline] 782*c3739801SMiguel Ojeda pub fn write(r: &mut Self, t: T) { 783*c3739801SMiguel Ojeda // SAFETY: We don't call any methods on `b` other than those provided by 784*c3739801SMiguel Ojeda // `ByteSliceMut`. 785*c3739801SMiguel Ojeda let b = unsafe { r.as_byte_slice_mut() }; 786*c3739801SMiguel Ojeda 787*c3739801SMiguel Ojeda // SAFETY: By postcondition on `as_byte_slice_mut`, we know that `b` is 788*c3739801SMiguel Ojeda // a valid size and alignment for `T`. By safety invariant on 789*c3739801SMiguel Ojeda // `ByteSlice`, we know that this is preserved via `.deref()`. Writing 790*c3739801SMiguel Ojeda // `t` to the buffer will allow all of the bytes of `t` to be accessed 791*c3739801SMiguel Ojeda // as a `[u8]`, but because `T: IntoBytes`, we know that this is sound. 792*c3739801SMiguel Ojeda unsafe { ptr::write(b.deref_mut().as_mut_ptr().cast::<T>(), t) } 793*c3739801SMiguel Ojeda } 794*c3739801SMiguel Ojeda } 795*c3739801SMiguel Ojeda 796*c3739801SMiguel Ojeda impl<B, T> Deref for Ref<B, T> 797*c3739801SMiguel Ojeda where 798*c3739801SMiguel Ojeda B: ByteSlice, 799*c3739801SMiguel Ojeda T: FromBytes + KnownLayout + Immutable + ?Sized, 800*c3739801SMiguel Ojeda { 801*c3739801SMiguel Ojeda type Target = T; 802*c3739801SMiguel Ojeda #[inline] 803*c3739801SMiguel Ojeda fn deref(&self) -> &T { 804*c3739801SMiguel Ojeda // Presumably unreachable, since we've guarded each constructor of `Ref`. 805*c3739801SMiguel Ojeda static_assert_dst_is_not_zst!(T); 806*c3739801SMiguel Ojeda 807*c3739801SMiguel Ojeda // SAFETY: We don't call any methods on `b` other than those provided by 808*c3739801SMiguel Ojeda // `ByteSlice`. 809*c3739801SMiguel Ojeda let b = unsafe { self.as_byte_slice() }; 810*c3739801SMiguel Ojeda let b = b.deref(); 811*c3739801SMiguel Ojeda 812*c3739801SMiguel Ojeda if let crate::layout::SizeInfo::Sized { .. } = T::LAYOUT.size_info { 813*c3739801SMiguel Ojeda let ptr = Ptr::from_ref(b); 814*c3739801SMiguel Ojeda // SAFETY: We just checked that `T: Sized`. By invariant on `r`, 815*c3739801SMiguel Ojeda // `b`'s size is equal to `size_of::<T>()`. 816*c3739801SMiguel Ojeda let ptr = unsafe { cast_for_sized::<T, _, _, _>(ptr) }; 817*c3739801SMiguel Ojeda 818*c3739801SMiguel Ojeda // SAFETY: None of the preceding transformations modifies the 819*c3739801SMiguel Ojeda // address of the pointer, and by invariant on `r`, we know that it 820*c3739801SMiguel Ojeda // is validly-aligned. 821*c3739801SMiguel Ojeda let ptr = unsafe { ptr.assume_alignment::<Aligned>() }; 822*c3739801SMiguel Ojeda return ptr.as_ref(); 823*c3739801SMiguel Ojeda } 824*c3739801SMiguel Ojeda 825*c3739801SMiguel Ojeda // PANICS: By postcondition on `as_byte_slice`, `b`'s size and alignment 826*c3739801SMiguel Ojeda // are valid for `T`, and by invariant on `ByteSlice`, these are 827*c3739801SMiguel Ojeda // preserved through `.deref()`, so this `unwrap` will not panic. 828*c3739801SMiguel Ojeda let ptr = Ptr::from_ref(b) 829*c3739801SMiguel Ojeda .try_cast_into_no_leftover::<T, BecauseImmutable>(None) 830*c3739801SMiguel Ojeda .expect("zerocopy internal error: Deref::deref should be infallible"); 831*c3739801SMiguel Ojeda let ptr = ptr.recall_validity(); 832*c3739801SMiguel Ojeda ptr.as_ref() 833*c3739801SMiguel Ojeda } 834*c3739801SMiguel Ojeda } 835*c3739801SMiguel Ojeda 836*c3739801SMiguel Ojeda impl<B, T> DerefMut for Ref<B, T> 837*c3739801SMiguel Ojeda where 838*c3739801SMiguel Ojeda B: ByteSliceMut, 839*c3739801SMiguel Ojeda // FIXME(#251): We can't remove `Immutable` here because it's required by 840*c3739801SMiguel Ojeda // the impl of `Deref`, which is a super-trait of `DerefMut`. Maybe we can 841*c3739801SMiguel Ojeda // add a separate inherent method for this? 842*c3739801SMiguel Ojeda T: FromBytes + IntoBytes + KnownLayout + Immutable + ?Sized, 843*c3739801SMiguel Ojeda { 844*c3739801SMiguel Ojeda #[inline] 845*c3739801SMiguel Ojeda fn deref_mut(&mut self) -> &mut T { 846*c3739801SMiguel Ojeda // Presumably unreachable, since we've guarded each constructor of `Ref`. 847*c3739801SMiguel Ojeda static_assert_dst_is_not_zst!(T); 848*c3739801SMiguel Ojeda 849*c3739801SMiguel Ojeda // SAFETY: We don't call any methods on `b` other than those provided by 850*c3739801SMiguel Ojeda // `ByteSliceMut`. 851*c3739801SMiguel Ojeda let b = unsafe { self.as_byte_slice_mut() }; 852*c3739801SMiguel Ojeda let b = b.deref_mut(); 853*c3739801SMiguel Ojeda 854*c3739801SMiguel Ojeda if let crate::layout::SizeInfo::Sized { .. } = T::LAYOUT.size_info { 855*c3739801SMiguel Ojeda let ptr = Ptr::from_mut(b); 856*c3739801SMiguel Ojeda // SAFETY: We just checked that `T: Sized`. By invariant on `r`, 857*c3739801SMiguel Ojeda // `b`'s size is equal to `size_of::<T>()`. 858*c3739801SMiguel Ojeda let ptr = unsafe { 859*c3739801SMiguel Ojeda cast_for_sized::< 860*c3739801SMiguel Ojeda T, 861*c3739801SMiguel Ojeda _, 862*c3739801SMiguel Ojeda (BecauseRead, BecauseExclusive), 863*c3739801SMiguel Ojeda (BecauseMutationCompatible, BecauseInvariantsEq), 864*c3739801SMiguel Ojeda >(ptr) 865*c3739801SMiguel Ojeda }; 866*c3739801SMiguel Ojeda 867*c3739801SMiguel Ojeda // SAFETY: None of the preceding transformations modifies the 868*c3739801SMiguel Ojeda // address of the pointer, and by invariant on `r`, we know that it 869*c3739801SMiguel Ojeda // is validly-aligned. 870*c3739801SMiguel Ojeda let ptr = unsafe { ptr.assume_alignment::<Aligned>() }; 871*c3739801SMiguel Ojeda return ptr.as_mut(); 872*c3739801SMiguel Ojeda } 873*c3739801SMiguel Ojeda 874*c3739801SMiguel Ojeda // PANICS: By postcondition on `as_byte_slice_mut`, `b`'s size and 875*c3739801SMiguel Ojeda // alignment are valid for `T`, and by invariant on `ByteSlice`, these 876*c3739801SMiguel Ojeda // are preserved through `.deref_mut()`, so this `unwrap` will not 877*c3739801SMiguel Ojeda // panic. 878*c3739801SMiguel Ojeda let ptr = Ptr::from_mut(b) 879*c3739801SMiguel Ojeda .try_cast_into_no_leftover::<T, BecauseExclusive>(None) 880*c3739801SMiguel Ojeda .expect("zerocopy internal error: DerefMut::deref_mut should be infallible"); 881*c3739801SMiguel Ojeda let ptr = ptr.recall_validity::<_, (_, (_, BecauseExclusive))>(); 882*c3739801SMiguel Ojeda ptr.as_mut() 883*c3739801SMiguel Ojeda } 884*c3739801SMiguel Ojeda } 885*c3739801SMiguel Ojeda 886*c3739801SMiguel Ojeda impl<T, B> Display for Ref<B, T> 887*c3739801SMiguel Ojeda where 888*c3739801SMiguel Ojeda B: ByteSlice, 889*c3739801SMiguel Ojeda T: FromBytes + Display + KnownLayout + Immutable + ?Sized, 890*c3739801SMiguel Ojeda { 891*c3739801SMiguel Ojeda #[inline] 892*c3739801SMiguel Ojeda fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { 893*c3739801SMiguel Ojeda let inner: &T = self; 894*c3739801SMiguel Ojeda inner.fmt(fmt) 895*c3739801SMiguel Ojeda } 896*c3739801SMiguel Ojeda } 897*c3739801SMiguel Ojeda 898*c3739801SMiguel Ojeda impl<T, B> Debug for Ref<B, T> 899*c3739801SMiguel Ojeda where 900*c3739801SMiguel Ojeda B: ByteSlice, 901*c3739801SMiguel Ojeda T: FromBytes + Debug + KnownLayout + Immutable + ?Sized, 902*c3739801SMiguel Ojeda { 903*c3739801SMiguel Ojeda #[inline] 904*c3739801SMiguel Ojeda fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { 905*c3739801SMiguel Ojeda let inner: &T = self; 906*c3739801SMiguel Ojeda fmt.debug_tuple("Ref").field(&inner).finish() 907*c3739801SMiguel Ojeda } 908*c3739801SMiguel Ojeda } 909*c3739801SMiguel Ojeda 910*c3739801SMiguel Ojeda impl<T, B> Eq for Ref<B, T> 911*c3739801SMiguel Ojeda where 912*c3739801SMiguel Ojeda B: ByteSlice, 913*c3739801SMiguel Ojeda T: FromBytes + Eq + KnownLayout + Immutable + ?Sized, 914*c3739801SMiguel Ojeda { 915*c3739801SMiguel Ojeda } 916*c3739801SMiguel Ojeda 917*c3739801SMiguel Ojeda impl<T, B> PartialEq for Ref<B, T> 918*c3739801SMiguel Ojeda where 919*c3739801SMiguel Ojeda B: ByteSlice, 920*c3739801SMiguel Ojeda T: FromBytes + PartialEq + KnownLayout + Immutable + ?Sized, 921*c3739801SMiguel Ojeda { 922*c3739801SMiguel Ojeda #[inline] 923*c3739801SMiguel Ojeda fn eq(&self, other: &Self) -> bool { 924*c3739801SMiguel Ojeda self.deref().eq(other.deref()) 925*c3739801SMiguel Ojeda } 926*c3739801SMiguel Ojeda } 927*c3739801SMiguel Ojeda 928*c3739801SMiguel Ojeda impl<T, B> Ord for Ref<B, T> 929*c3739801SMiguel Ojeda where 930*c3739801SMiguel Ojeda B: ByteSlice, 931*c3739801SMiguel Ojeda T: FromBytes + Ord + KnownLayout + Immutable + ?Sized, 932*c3739801SMiguel Ojeda { 933*c3739801SMiguel Ojeda #[inline] 934*c3739801SMiguel Ojeda fn cmp(&self, other: &Self) -> Ordering { 935*c3739801SMiguel Ojeda let inner: &T = self; 936*c3739801SMiguel Ojeda let other_inner: &T = other; 937*c3739801SMiguel Ojeda inner.cmp(other_inner) 938*c3739801SMiguel Ojeda } 939*c3739801SMiguel Ojeda } 940*c3739801SMiguel Ojeda 941*c3739801SMiguel Ojeda impl<T, B> PartialOrd for Ref<B, T> 942*c3739801SMiguel Ojeda where 943*c3739801SMiguel Ojeda B: ByteSlice, 944*c3739801SMiguel Ojeda T: FromBytes + PartialOrd + KnownLayout + Immutable + ?Sized, 945*c3739801SMiguel Ojeda { 946*c3739801SMiguel Ojeda #[inline] 947*c3739801SMiguel Ojeda fn partial_cmp(&self, other: &Self) -> Option<Ordering> { 948*c3739801SMiguel Ojeda let inner: &T = self; 949*c3739801SMiguel Ojeda let other_inner: &T = other; 950*c3739801SMiguel Ojeda inner.partial_cmp(other_inner) 951*c3739801SMiguel Ojeda } 952*c3739801SMiguel Ojeda } 953*c3739801SMiguel Ojeda 954*c3739801SMiguel Ojeda /// # Safety 955*c3739801SMiguel Ojeda /// 956*c3739801SMiguel Ojeda /// `T: Sized` and `ptr`'s referent must have size `size_of::<T>()`. 957*c3739801SMiguel Ojeda #[inline(always)] 958*c3739801SMiguel Ojeda unsafe fn cast_for_sized<'a, T, A, R, S>( 959*c3739801SMiguel Ojeda ptr: Ptr<'a, [u8], (A, Aligned, Valid)>, 960*c3739801SMiguel Ojeda ) -> Ptr<'a, T, (A, Unaligned, Valid)> 961*c3739801SMiguel Ojeda where 962*c3739801SMiguel Ojeda T: FromBytes + KnownLayout + ?Sized, 963*c3739801SMiguel Ojeda A: crate::invariant::Aliasing, 964*c3739801SMiguel Ojeda [u8]: MutationCompatible<T, A, Initialized, Initialized, R>, 965*c3739801SMiguel Ojeda T: TransmuteFromPtr<T, A, Initialized, Valid, crate::pointer::cast::IdCast, S>, 966*c3739801SMiguel Ojeda { 967*c3739801SMiguel Ojeda use crate::pointer::cast::{Cast, Project}; 968*c3739801SMiguel Ojeda 969*c3739801SMiguel Ojeda enum CastForSized {} 970*c3739801SMiguel Ojeda 971*c3739801SMiguel Ojeda // SAFETY: `CastForSized` is only used below with the input `ptr`, which the 972*c3739801SMiguel Ojeda // caller promises has size `size_of::<T>()`. Thus, the referent produced in 973*c3739801SMiguel Ojeda // this cast has the same size as `ptr`'s referent. All operations preserve 974*c3739801SMiguel Ojeda // provenance. 975*c3739801SMiguel Ojeda unsafe impl<T: ?Sized + KnownLayout> Project<[u8], T> for CastForSized { 976*c3739801SMiguel Ojeda #[inline(always)] 977*c3739801SMiguel Ojeda fn project(src: PtrInner<'_, [u8]>) -> *mut T { 978*c3739801SMiguel Ojeda T::raw_from_ptr_len( 979*c3739801SMiguel Ojeda src.as_non_null().cast(), 980*c3739801SMiguel Ojeda <T::PointerMetadata as crate::PointerMetadata>::from_elem_count(0), 981*c3739801SMiguel Ojeda ) 982*c3739801SMiguel Ojeda .as_ptr() 983*c3739801SMiguel Ojeda } 984*c3739801SMiguel Ojeda } 985*c3739801SMiguel Ojeda 986*c3739801SMiguel Ojeda // SAFETY: The `Project::project` impl preserves referent address. 987*c3739801SMiguel Ojeda unsafe impl<T: ?Sized + KnownLayout> Cast<[u8], T> for CastForSized {} 988*c3739801SMiguel Ojeda 989*c3739801SMiguel Ojeda ptr.recall_validity::<Initialized, (_, (_, _))>() 990*c3739801SMiguel Ojeda .cast::<_, CastForSized, _>() 991*c3739801SMiguel Ojeda .recall_validity::<Valid, _>() 992*c3739801SMiguel Ojeda } 993*c3739801SMiguel Ojeda 994*c3739801SMiguel Ojeda #[cfg(test)] 995*c3739801SMiguel Ojeda #[allow(clippy::assertions_on_result_states)] 996*c3739801SMiguel Ojeda mod tests { 997*c3739801SMiguel Ojeda use core::convert::TryInto as _; 998*c3739801SMiguel Ojeda 999*c3739801SMiguel Ojeda use super::*; 1000*c3739801SMiguel Ojeda use crate::util::testutil::*; 1001*c3739801SMiguel Ojeda 1002*c3739801SMiguel Ojeda #[test] 1003*c3739801SMiguel Ojeda fn test_mut_slice_into_ref() { 1004*c3739801SMiguel Ojeda // Prior to #1260/#1299, calling `into_ref` on a `&mut [u8]`-backed 1005*c3739801SMiguel Ojeda // `Ref` was not supported. 1006*c3739801SMiguel Ojeda let mut buf = [0u8]; 1007*c3739801SMiguel Ojeda let r = Ref::<&mut [u8], u8>::from_bytes(&mut buf).unwrap(); 1008*c3739801SMiguel Ojeda assert_eq!(Ref::into_ref(r), &0); 1009*c3739801SMiguel Ojeda } 1010*c3739801SMiguel Ojeda 1011*c3739801SMiguel Ojeda #[test] 1012*c3739801SMiguel Ojeda fn test_address() { 1013*c3739801SMiguel Ojeda // Test that the `Deref` and `DerefMut` implementations return a 1014*c3739801SMiguel Ojeda // reference which points to the right region of memory. 1015*c3739801SMiguel Ojeda 1016*c3739801SMiguel Ojeda let buf = [0]; 1017*c3739801SMiguel Ojeda let r = Ref::<_, u8>::from_bytes(&buf[..]).unwrap(); 1018*c3739801SMiguel Ojeda let buf_ptr = buf.as_ptr(); 1019*c3739801SMiguel Ojeda let deref_ptr: *const u8 = r.deref(); 1020*c3739801SMiguel Ojeda assert_eq!(buf_ptr, deref_ptr); 1021*c3739801SMiguel Ojeda 1022*c3739801SMiguel Ojeda let buf = [0]; 1023*c3739801SMiguel Ojeda let r = Ref::<_, [u8]>::from_bytes(&buf[..]).unwrap(); 1024*c3739801SMiguel Ojeda let buf_ptr = buf.as_ptr(); 1025*c3739801SMiguel Ojeda let deref_ptr = r.deref().as_ptr(); 1026*c3739801SMiguel Ojeda assert_eq!(buf_ptr, deref_ptr); 1027*c3739801SMiguel Ojeda } 1028*c3739801SMiguel Ojeda 1029*c3739801SMiguel Ojeda // Verify that values written to a `Ref` are properly shared between the 1030*c3739801SMiguel Ojeda // typed and untyped representations, that reads via `deref` and `read` 1031*c3739801SMiguel Ojeda // behave the same, and that writes via `deref_mut` and `write` behave the 1032*c3739801SMiguel Ojeda // same. 1033*c3739801SMiguel Ojeda fn test_new_helper(mut r: Ref<&mut [u8], AU64>) { 1034*c3739801SMiguel Ojeda // assert that the value starts at 0 1035*c3739801SMiguel Ojeda assert_eq!(*r, AU64(0)); 1036*c3739801SMiguel Ojeda assert_eq!(Ref::read(&r), AU64(0)); 1037*c3739801SMiguel Ojeda 1038*c3739801SMiguel Ojeda // Assert that values written to the typed value are reflected in the 1039*c3739801SMiguel Ojeda // byte slice. 1040*c3739801SMiguel Ojeda const VAL1: AU64 = AU64(0xFF00FF00FF00FF00); 1041*c3739801SMiguel Ojeda *r = VAL1; 1042*c3739801SMiguel Ojeda assert_eq!(Ref::bytes(&r), &VAL1.to_bytes()); 1043*c3739801SMiguel Ojeda *r = AU64(0); 1044*c3739801SMiguel Ojeda Ref::write(&mut r, VAL1); 1045*c3739801SMiguel Ojeda assert_eq!(Ref::bytes(&r), &VAL1.to_bytes()); 1046*c3739801SMiguel Ojeda 1047*c3739801SMiguel Ojeda // Assert that values written to the byte slice are reflected in the 1048*c3739801SMiguel Ojeda // typed value. 1049*c3739801SMiguel Ojeda const VAL2: AU64 = AU64(!VAL1.0); // different from `VAL1` 1050*c3739801SMiguel Ojeda Ref::bytes_mut(&mut r).copy_from_slice(&VAL2.to_bytes()[..]); 1051*c3739801SMiguel Ojeda assert_eq!(*r, VAL2); 1052*c3739801SMiguel Ojeda assert_eq!(Ref::read(&r), VAL2); 1053*c3739801SMiguel Ojeda } 1054*c3739801SMiguel Ojeda 1055*c3739801SMiguel Ojeda // Verify that values written to a `Ref` are properly shared between the 1056*c3739801SMiguel Ojeda // typed and untyped representations; pass a value with `typed_len` `AU64`s 1057*c3739801SMiguel Ojeda // backed by an array of `typed_len * 8` bytes. 1058*c3739801SMiguel Ojeda fn test_new_helper_slice(mut r: Ref<&mut [u8], [AU64]>, typed_len: usize) { 1059*c3739801SMiguel Ojeda // Assert that the value starts out zeroed. 1060*c3739801SMiguel Ojeda assert_eq!(&*r, vec![AU64(0); typed_len].as_slice()); 1061*c3739801SMiguel Ojeda 1062*c3739801SMiguel Ojeda // Check the backing storage is the exact same slice. 1063*c3739801SMiguel Ojeda let untyped_len = typed_len * 8; 1064*c3739801SMiguel Ojeda assert_eq!(Ref::bytes(&r).len(), untyped_len); 1065*c3739801SMiguel Ojeda assert_eq!(Ref::bytes(&r).as_ptr(), r.as_ptr().cast::<u8>()); 1066*c3739801SMiguel Ojeda 1067*c3739801SMiguel Ojeda // Assert that values written to the typed value are reflected in the 1068*c3739801SMiguel Ojeda // byte slice. 1069*c3739801SMiguel Ojeda const VAL1: AU64 = AU64(0xFF00FF00FF00FF00); 1070*c3739801SMiguel Ojeda for typed in &mut *r { 1071*c3739801SMiguel Ojeda *typed = VAL1; 1072*c3739801SMiguel Ojeda } 1073*c3739801SMiguel Ojeda assert_eq!(Ref::bytes(&r), VAL1.0.to_ne_bytes().repeat(typed_len).as_slice()); 1074*c3739801SMiguel Ojeda 1075*c3739801SMiguel Ojeda // Assert that values written to the byte slice are reflected in the 1076*c3739801SMiguel Ojeda // typed value. 1077*c3739801SMiguel Ojeda const VAL2: AU64 = AU64(!VAL1.0); // different from VAL1 1078*c3739801SMiguel Ojeda Ref::bytes_mut(&mut r).copy_from_slice(&VAL2.0.to_ne_bytes().repeat(typed_len)); 1079*c3739801SMiguel Ojeda assert!(r.iter().copied().all(|x| x == VAL2)); 1080*c3739801SMiguel Ojeda } 1081*c3739801SMiguel Ojeda 1082*c3739801SMiguel Ojeda #[test] 1083*c3739801SMiguel Ojeda fn test_new_aligned_sized() { 1084*c3739801SMiguel Ojeda // Test that a properly-aligned, properly-sized buffer works for new, 1085*c3739801SMiguel Ojeda // new_from_prefix, and new_from_suffix, and that new_from_prefix and 1086*c3739801SMiguel Ojeda // new_from_suffix return empty slices. Test that a properly-aligned 1087*c3739801SMiguel Ojeda // buffer whose length is a multiple of the element size works for 1088*c3739801SMiguel Ojeda // new_slice. 1089*c3739801SMiguel Ojeda 1090*c3739801SMiguel Ojeda // A buffer with an alignment of 8. 1091*c3739801SMiguel Ojeda let mut buf = Align::<[u8; 8], AU64>::default(); 1092*c3739801SMiguel Ojeda // `buf.t` should be aligned to 8, so this should always succeed. 1093*c3739801SMiguel Ojeda test_new_helper(Ref::<_, AU64>::from_bytes(&mut buf.t[..]).unwrap()); 1094*c3739801SMiguel Ojeda { 1095*c3739801SMiguel Ojeda // In a block so that `r` and `suffix` don't live too long. 1096*c3739801SMiguel Ojeda buf.set_default(); 1097*c3739801SMiguel Ojeda let (r, suffix) = Ref::<_, AU64>::from_prefix(&mut buf.t[..]).unwrap(); 1098*c3739801SMiguel Ojeda assert!(suffix.is_empty()); 1099*c3739801SMiguel Ojeda test_new_helper(r); 1100*c3739801SMiguel Ojeda } 1101*c3739801SMiguel Ojeda { 1102*c3739801SMiguel Ojeda buf.set_default(); 1103*c3739801SMiguel Ojeda let (prefix, r) = Ref::<_, AU64>::from_suffix(&mut buf.t[..]).unwrap(); 1104*c3739801SMiguel Ojeda assert!(prefix.is_empty()); 1105*c3739801SMiguel Ojeda test_new_helper(r); 1106*c3739801SMiguel Ojeda } 1107*c3739801SMiguel Ojeda 1108*c3739801SMiguel Ojeda // A buffer with alignment 8 and length 24. We choose this length very 1109*c3739801SMiguel Ojeda // intentionally: if we instead used length 16, then the prefix and 1110*c3739801SMiguel Ojeda // suffix lengths would be identical. In the past, we used length 16, 1111*c3739801SMiguel Ojeda // which resulted in this test failing to discover the bug uncovered in 1112*c3739801SMiguel Ojeda // #506. 1113*c3739801SMiguel Ojeda let mut buf = Align::<[u8; 24], AU64>::default(); 1114*c3739801SMiguel Ojeda // `buf.t` should be aligned to 8 and have a length which is a multiple 1115*c3739801SMiguel Ojeda // of `size_of::<AU64>()`, so this should always succeed. 1116*c3739801SMiguel Ojeda test_new_helper_slice(Ref::<_, [AU64]>::from_bytes(&mut buf.t[..]).unwrap(), 3); 1117*c3739801SMiguel Ojeda buf.set_default(); 1118*c3739801SMiguel Ojeda let r = Ref::<_, [AU64]>::from_bytes_with_elems(&mut buf.t[..], 3).unwrap(); 1119*c3739801SMiguel Ojeda test_new_helper_slice(r, 3); 1120*c3739801SMiguel Ojeda 1121*c3739801SMiguel Ojeda let ascending: [u8; 24] = (0..24).collect::<Vec<_>>().try_into().unwrap(); 1122*c3739801SMiguel Ojeda // 16 ascending bytes followed by 8 zeros. 1123*c3739801SMiguel Ojeda let mut ascending_prefix = ascending; 1124*c3739801SMiguel Ojeda ascending_prefix[16..].copy_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0]); 1125*c3739801SMiguel Ojeda // 8 zeros followed by 16 ascending bytes. 1126*c3739801SMiguel Ojeda let mut ascending_suffix = ascending; 1127*c3739801SMiguel Ojeda ascending_suffix[..8].copy_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0]); 1128*c3739801SMiguel Ojeda { 1129*c3739801SMiguel Ojeda buf.t = ascending_suffix; 1130*c3739801SMiguel Ojeda let (r, suffix) = Ref::<_, [AU64]>::from_prefix_with_elems(&mut buf.t[..], 1).unwrap(); 1131*c3739801SMiguel Ojeda assert_eq!(suffix, &ascending[8..]); 1132*c3739801SMiguel Ojeda test_new_helper_slice(r, 1); 1133*c3739801SMiguel Ojeda } 1134*c3739801SMiguel Ojeda { 1135*c3739801SMiguel Ojeda buf.t = ascending_prefix; 1136*c3739801SMiguel Ojeda let (prefix, r) = Ref::<_, [AU64]>::from_suffix_with_elems(&mut buf.t[..], 1).unwrap(); 1137*c3739801SMiguel Ojeda assert_eq!(prefix, &ascending[..16]); 1138*c3739801SMiguel Ojeda test_new_helper_slice(r, 1); 1139*c3739801SMiguel Ojeda } 1140*c3739801SMiguel Ojeda } 1141*c3739801SMiguel Ojeda 1142*c3739801SMiguel Ojeda #[test] 1143*c3739801SMiguel Ojeda fn test_new_oversized() { 1144*c3739801SMiguel Ojeda // Test that a properly-aligned, overly-sized buffer works for 1145*c3739801SMiguel Ojeda // `new_from_prefix` and `new_from_suffix`, and that they return the 1146*c3739801SMiguel Ojeda // remainder and prefix of the slice respectively. 1147*c3739801SMiguel Ojeda 1148*c3739801SMiguel Ojeda let mut buf = Align::<[u8; 16], AU64>::default(); 1149*c3739801SMiguel Ojeda { 1150*c3739801SMiguel Ojeda // In a block so that `r` and `suffix` don't live too long. `buf.t` 1151*c3739801SMiguel Ojeda // should be aligned to 8, so this should always succeed. 1152*c3739801SMiguel Ojeda let (r, suffix) = Ref::<_, AU64>::from_prefix(&mut buf.t[..]).unwrap(); 1153*c3739801SMiguel Ojeda assert_eq!(suffix.len(), 8); 1154*c3739801SMiguel Ojeda test_new_helper(r); 1155*c3739801SMiguel Ojeda } 1156*c3739801SMiguel Ojeda { 1157*c3739801SMiguel Ojeda buf.set_default(); 1158*c3739801SMiguel Ojeda // `buf.t` should be aligned to 8, so this should always succeed. 1159*c3739801SMiguel Ojeda let (prefix, r) = Ref::<_, AU64>::from_suffix(&mut buf.t[..]).unwrap(); 1160*c3739801SMiguel Ojeda assert_eq!(prefix.len(), 8); 1161*c3739801SMiguel Ojeda test_new_helper(r); 1162*c3739801SMiguel Ojeda } 1163*c3739801SMiguel Ojeda } 1164*c3739801SMiguel Ojeda 1165*c3739801SMiguel Ojeda #[test] 1166*c3739801SMiguel Ojeda #[allow(clippy::cognitive_complexity)] 1167*c3739801SMiguel Ojeda fn test_new_error() { 1168*c3739801SMiguel Ojeda // Fail because the buffer is too large. 1169*c3739801SMiguel Ojeda 1170*c3739801SMiguel Ojeda // A buffer with an alignment of 8. 1171*c3739801SMiguel Ojeda let buf = Align::<[u8; 16], AU64>::default(); 1172*c3739801SMiguel Ojeda // `buf.t` should be aligned to 8, so only the length check should fail. 1173*c3739801SMiguel Ojeda assert!(Ref::<_, AU64>::from_bytes(&buf.t[..]).is_err()); 1174*c3739801SMiguel Ojeda 1175*c3739801SMiguel Ojeda // Fail because the buffer is too small. 1176*c3739801SMiguel Ojeda 1177*c3739801SMiguel Ojeda // A buffer with an alignment of 8. 1178*c3739801SMiguel Ojeda let buf = Align::<[u8; 4], AU64>::default(); 1179*c3739801SMiguel Ojeda // `buf.t` should be aligned to 8, so only the length check should fail. 1180*c3739801SMiguel Ojeda assert!(Ref::<_, AU64>::from_bytes(&buf.t[..]).is_err()); 1181*c3739801SMiguel Ojeda assert!(Ref::<_, AU64>::from_prefix(&buf.t[..]).is_err()); 1182*c3739801SMiguel Ojeda assert!(Ref::<_, AU64>::from_suffix(&buf.t[..]).is_err()); 1183*c3739801SMiguel Ojeda 1184*c3739801SMiguel Ojeda // Fail because the length is not a multiple of the element size. 1185*c3739801SMiguel Ojeda 1186*c3739801SMiguel Ojeda let buf = Align::<[u8; 12], AU64>::default(); 1187*c3739801SMiguel Ojeda // `buf.t` has length 12, but element size is 8. 1188*c3739801SMiguel Ojeda assert!(Ref::<_, [AU64]>::from_bytes(&buf.t[..]).is_err()); 1189*c3739801SMiguel Ojeda 1190*c3739801SMiguel Ojeda // Fail because the buffer is too short. 1191*c3739801SMiguel Ojeda let buf = Align::<[u8; 12], AU64>::default(); 1192*c3739801SMiguel Ojeda // `buf.t` has length 12, but the element size is 8 (and we're expecting 1193*c3739801SMiguel Ojeda // two of them). For each function, we test with a length that would 1194*c3739801SMiguel Ojeda // cause the size to overflow `usize`, and with a normal length that 1195*c3739801SMiguel Ojeda // will fail thanks to the buffer being too short; these are different 1196*c3739801SMiguel Ojeda // error paths, and while the error types are the same, the distinction 1197*c3739801SMiguel Ojeda // shows up in code coverage metrics. 1198*c3739801SMiguel Ojeda let n = (usize::MAX / mem::size_of::<AU64>()) + 1; 1199*c3739801SMiguel Ojeda assert!(Ref::<_, [AU64]>::from_bytes_with_elems(&buf.t[..], n).is_err()); 1200*c3739801SMiguel Ojeda assert!(Ref::<_, [AU64]>::from_bytes_with_elems(&buf.t[..], 2).is_err()); 1201*c3739801SMiguel Ojeda assert!(Ref::<_, [AU64]>::from_prefix_with_elems(&buf.t[..], n).is_err()); 1202*c3739801SMiguel Ojeda assert!(Ref::<_, [AU64]>::from_prefix_with_elems(&buf.t[..], 2).is_err()); 1203*c3739801SMiguel Ojeda assert!(Ref::<_, [AU64]>::from_suffix_with_elems(&buf.t[..], n).is_err()); 1204*c3739801SMiguel Ojeda assert!(Ref::<_, [AU64]>::from_suffix_with_elems(&buf.t[..], 2).is_err()); 1205*c3739801SMiguel Ojeda 1206*c3739801SMiguel Ojeda // Fail because the alignment is insufficient. 1207*c3739801SMiguel Ojeda 1208*c3739801SMiguel Ojeda // A buffer with an alignment of 8. An odd buffer size is chosen so that 1209*c3739801SMiguel Ojeda // the last byte of the buffer has odd alignment. 1210*c3739801SMiguel Ojeda let buf = Align::<[u8; 13], AU64>::default(); 1211*c3739801SMiguel Ojeda // Slicing from 1, we get a buffer with size 12 (so the length check 1212*c3739801SMiguel Ojeda // should succeed) but an alignment of only 1, which is insufficient. 1213*c3739801SMiguel Ojeda assert!(Ref::<_, AU64>::from_bytes(&buf.t[1..]).is_err()); 1214*c3739801SMiguel Ojeda assert!(Ref::<_, AU64>::from_prefix(&buf.t[1..]).is_err()); 1215*c3739801SMiguel Ojeda assert!(Ref::<_, [AU64]>::from_bytes(&buf.t[1..]).is_err()); 1216*c3739801SMiguel Ojeda assert!(Ref::<_, [AU64]>::from_bytes_with_elems(&buf.t[1..], 1).is_err()); 1217*c3739801SMiguel Ojeda assert!(Ref::<_, [AU64]>::from_prefix_with_elems(&buf.t[1..], 1).is_err()); 1218*c3739801SMiguel Ojeda assert!(Ref::<_, [AU64]>::from_suffix_with_elems(&buf.t[1..], 1).is_err()); 1219*c3739801SMiguel Ojeda // Slicing is unnecessary here because `new_from_suffix` uses the suffix 1220*c3739801SMiguel Ojeda // of the slice, which has odd alignment. 1221*c3739801SMiguel Ojeda assert!(Ref::<_, AU64>::from_suffix(&buf.t[..]).is_err()); 1222*c3739801SMiguel Ojeda 1223*c3739801SMiguel Ojeda // Fail due to arithmetic overflow. 1224*c3739801SMiguel Ojeda 1225*c3739801SMiguel Ojeda let buf = Align::<[u8; 16], AU64>::default(); 1226*c3739801SMiguel Ojeda let unreasonable_len = usize::MAX / mem::size_of::<AU64>() + 1; 1227*c3739801SMiguel Ojeda assert!(Ref::<_, [AU64]>::from_prefix_with_elems(&buf.t[..], unreasonable_len).is_err()); 1228*c3739801SMiguel Ojeda assert!(Ref::<_, [AU64]>::from_suffix_with_elems(&buf.t[..], unreasonable_len).is_err()); 1229*c3739801SMiguel Ojeda } 1230*c3739801SMiguel Ojeda 1231*c3739801SMiguel Ojeda #[test] 1232*c3739801SMiguel Ojeda #[allow(unstable_name_collisions)] 1233*c3739801SMiguel Ojeda #[allow(clippy::as_conversions)] 1234*c3739801SMiguel Ojeda fn test_into_ref_mut() { 1235*c3739801SMiguel Ojeda #[allow(unused)] 1236*c3739801SMiguel Ojeda use crate::util::AsAddress as _; 1237*c3739801SMiguel Ojeda 1238*c3739801SMiguel Ojeda let mut buf = Align::<[u8; 8], u64>::default(); 1239*c3739801SMiguel Ojeda let r = Ref::<_, u64>::from_bytes(&buf.t[..]).unwrap(); 1240*c3739801SMiguel Ojeda let rf = Ref::into_ref(r); 1241*c3739801SMiguel Ojeda assert_eq!(rf, &0u64); 1242*c3739801SMiguel Ojeda let buf_addr = (&buf.t as *const [u8; 8]).addr(); 1243*c3739801SMiguel Ojeda assert_eq!((rf as *const u64).addr(), buf_addr); 1244*c3739801SMiguel Ojeda 1245*c3739801SMiguel Ojeda let r = Ref::<_, u64>::from_bytes(&mut buf.t[..]).unwrap(); 1246*c3739801SMiguel Ojeda let rf = Ref::into_mut(r); 1247*c3739801SMiguel Ojeda assert_eq!(rf, &mut 0u64); 1248*c3739801SMiguel Ojeda assert_eq!((rf as *mut u64).addr(), buf_addr); 1249*c3739801SMiguel Ojeda 1250*c3739801SMiguel Ojeda *rf = u64::MAX; 1251*c3739801SMiguel Ojeda assert_eq!(buf.t, [0xFF; 8]); 1252*c3739801SMiguel Ojeda } 1253*c3739801SMiguel Ojeda 1254*c3739801SMiguel Ojeda #[test] 1255*c3739801SMiguel Ojeda fn test_display_debug() { 1256*c3739801SMiguel Ojeda let buf = Align::<[u8; 8], u64>::default(); 1257*c3739801SMiguel Ojeda let r = Ref::<_, u64>::from_bytes(&buf.t[..]).unwrap(); 1258*c3739801SMiguel Ojeda assert_eq!(format!("{}", r), "0"); 1259*c3739801SMiguel Ojeda assert_eq!(format!("{:?}", r), "Ref(0)"); 1260*c3739801SMiguel Ojeda 1261*c3739801SMiguel Ojeda let buf = Align::<[u8; 8], u64>::default(); 1262*c3739801SMiguel Ojeda let r = Ref::<_, [u64]>::from_bytes(&buf.t[..]).unwrap(); 1263*c3739801SMiguel Ojeda assert_eq!(format!("{:?}", r), "Ref([0])"); 1264*c3739801SMiguel Ojeda } 1265*c3739801SMiguel Ojeda 1266*c3739801SMiguel Ojeda #[test] 1267*c3739801SMiguel Ojeda fn test_eq() { 1268*c3739801SMiguel Ojeda let buf1 = 0_u64; 1269*c3739801SMiguel Ojeda let r1 = Ref::<_, u64>::from_bytes(buf1.as_bytes()).unwrap(); 1270*c3739801SMiguel Ojeda let buf2 = 0_u64; 1271*c3739801SMiguel Ojeda let r2 = Ref::<_, u64>::from_bytes(buf2.as_bytes()).unwrap(); 1272*c3739801SMiguel Ojeda assert_eq!(r1, r2); 1273*c3739801SMiguel Ojeda } 1274*c3739801SMiguel Ojeda 1275*c3739801SMiguel Ojeda #[test] 1276*c3739801SMiguel Ojeda fn test_ne() { 1277*c3739801SMiguel Ojeda let buf1 = 0_u64; 1278*c3739801SMiguel Ojeda let r1 = Ref::<_, u64>::from_bytes(buf1.as_bytes()).unwrap(); 1279*c3739801SMiguel Ojeda let buf2 = 1_u64; 1280*c3739801SMiguel Ojeda let r2 = Ref::<_, u64>::from_bytes(buf2.as_bytes()).unwrap(); 1281*c3739801SMiguel Ojeda assert_ne!(r1, r2); 1282*c3739801SMiguel Ojeda } 1283*c3739801SMiguel Ojeda 1284*c3739801SMiguel Ojeda #[test] 1285*c3739801SMiguel Ojeda fn test_ord() { 1286*c3739801SMiguel Ojeda let buf1 = 0_u64; 1287*c3739801SMiguel Ojeda let r1 = Ref::<_, u64>::from_bytes(buf1.as_bytes()).unwrap(); 1288*c3739801SMiguel Ojeda let buf2 = 1_u64; 1289*c3739801SMiguel Ojeda let r2 = Ref::<_, u64>::from_bytes(buf2.as_bytes()).unwrap(); 1290*c3739801SMiguel Ojeda assert!(r1 < r2); 1291*c3739801SMiguel Ojeda assert_eq!(PartialOrd::partial_cmp(&r1, &r2), Some(Ordering::Less)); 1292*c3739801SMiguel Ojeda assert_eq!(Ord::cmp(&r1, &r2), Ordering::Less); 1293*c3739801SMiguel Ojeda } 1294*c3739801SMiguel Ojeda } 1295*c3739801SMiguel Ojeda 1296*c3739801SMiguel Ojeda #[cfg(all(test, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS))] 1297*c3739801SMiguel Ojeda mod benches { 1298*c3739801SMiguel Ojeda use test::{self, Bencher}; 1299*c3739801SMiguel Ojeda 1300*c3739801SMiguel Ojeda use super::*; 1301*c3739801SMiguel Ojeda use crate::util::testutil::*; 1302*c3739801SMiguel Ojeda 1303*c3739801SMiguel Ojeda #[bench] 1304*c3739801SMiguel Ojeda fn bench_from_bytes_sized(b: &mut Bencher) { 1305*c3739801SMiguel Ojeda let buf = Align::<[u8; 8], AU64>::default(); 1306*c3739801SMiguel Ojeda // `buf.t` should be aligned to 8, so this should always succeed. 1307*c3739801SMiguel Ojeda let bytes = &buf.t[..]; 1308*c3739801SMiguel Ojeda b.iter(|| test::black_box(Ref::<_, AU64>::from_bytes(test::black_box(bytes)).unwrap())); 1309*c3739801SMiguel Ojeda } 1310*c3739801SMiguel Ojeda 1311*c3739801SMiguel Ojeda #[bench] 1312*c3739801SMiguel Ojeda fn bench_into_ref_sized(b: &mut Bencher) { 1313*c3739801SMiguel Ojeda let buf = Align::<[u8; 8], AU64>::default(); 1314*c3739801SMiguel Ojeda let bytes = &buf.t[..]; 1315*c3739801SMiguel Ojeda let r = Ref::<_, AU64>::from_bytes(bytes).unwrap(); 1316*c3739801SMiguel Ojeda b.iter(|| test::black_box(Ref::into_ref(test::black_box(r)))); 1317*c3739801SMiguel Ojeda } 1318*c3739801SMiguel Ojeda 1319*c3739801SMiguel Ojeda #[bench] 1320*c3739801SMiguel Ojeda fn bench_into_mut_sized(b: &mut Bencher) { 1321*c3739801SMiguel Ojeda let mut buf = Align::<[u8; 8], AU64>::default(); 1322*c3739801SMiguel Ojeda let buf = &mut buf.t[..]; 1323*c3739801SMiguel Ojeda let _ = Ref::<_, AU64>::from_bytes(&mut *buf).unwrap(); 1324*c3739801SMiguel Ojeda b.iter(move || { 1325*c3739801SMiguel Ojeda // SAFETY: The preceding `from_bytes` succeeded, and so we know that 1326*c3739801SMiguel Ojeda // `buf` is validly-aligned and has the correct length. 1327*c3739801SMiguel Ojeda let r = unsafe { Ref::<&mut [u8], AU64>::new_unchecked(&mut *buf) }; 1328*c3739801SMiguel Ojeda test::black_box(Ref::into_mut(test::black_box(r))); 1329*c3739801SMiguel Ojeda }); 1330*c3739801SMiguel Ojeda } 1331*c3739801SMiguel Ojeda 1332*c3739801SMiguel Ojeda #[bench] 1333*c3739801SMiguel Ojeda fn bench_deref_sized(b: &mut Bencher) { 1334*c3739801SMiguel Ojeda let buf = Align::<[u8; 8], AU64>::default(); 1335*c3739801SMiguel Ojeda let bytes = &buf.t[..]; 1336*c3739801SMiguel Ojeda let r = Ref::<_, AU64>::from_bytes(bytes).unwrap(); 1337*c3739801SMiguel Ojeda b.iter(|| { 1338*c3739801SMiguel Ojeda let temp = test::black_box(r); 1339*c3739801SMiguel Ojeda test::black_box(temp.deref()); 1340*c3739801SMiguel Ojeda }); 1341*c3739801SMiguel Ojeda } 1342*c3739801SMiguel Ojeda 1343*c3739801SMiguel Ojeda #[bench] 1344*c3739801SMiguel Ojeda fn bench_deref_mut_sized(b: &mut Bencher) { 1345*c3739801SMiguel Ojeda let mut buf = Align::<[u8; 8], AU64>::default(); 1346*c3739801SMiguel Ojeda let buf = &mut buf.t[..]; 1347*c3739801SMiguel Ojeda let _ = Ref::<_, AU64>::from_bytes(&mut *buf).unwrap(); 1348*c3739801SMiguel Ojeda b.iter(|| { 1349*c3739801SMiguel Ojeda // SAFETY: The preceding `from_bytes` succeeded, and so we know that 1350*c3739801SMiguel Ojeda // `buf` is validly-aligned and has the correct length. 1351*c3739801SMiguel Ojeda let r = unsafe { Ref::<&mut [u8], AU64>::new_unchecked(&mut *buf) }; 1352*c3739801SMiguel Ojeda let mut temp = test::black_box(r); 1353*c3739801SMiguel Ojeda test::black_box(temp.deref_mut()); 1354*c3739801SMiguel Ojeda }); 1355*c3739801SMiguel Ojeda } 1356*c3739801SMiguel Ojeda } 1357