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