xref: /linux/rust/zerocopy/src/ref.rs (revision c37398010a05055e78cf0c75defb90df06c4e999)
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