Skip to main content

zerocopy/
ref.rs

1// SPDX-License-Identifier: (BSD-2-Clause OR Apache-2.0) OR MIT
2//
3// Copyright 2024 The Fuchsia Authors
4//
5// Licensed under the 2-Clause BSD License <LICENSE-BSD or
6// https://opensource.org/license/bsd-2-clause>, Apache License, Version 2.0
7// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
8// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
9// This file may not be copied, modified, or distributed except according to
10// those terms.
11use super::*;
12use crate::pointer::{
13    BecauseMutationCompatible, BecauseSharedCompatible, MutationCompatible, TransmuteFromPtr,
14};
15
16mod def {
17    use core::marker::PhantomData;
18
19    use crate::{
20        ByteSlice, ByteSliceMut, CloneableByteSlice, CopyableByteSlice, IntoByteSlice,
21        IntoByteSliceMut, KnownLayout, PointerMetadata,
22    };
23
24    /// A typed reference derived from a byte slice.
25    ///
26    /// A `Ref<B, T>` is a reference to a `T` which is stored in a byte slice, `B`.
27    /// Unlike a native reference (`&T` or `&mut T`), `Ref<B, T>` has the same
28    /// mutability as the byte slice it was constructed from (`B`).
29    ///
30    /// # Examples
31    ///
32    /// `Ref` can be used to treat a sequence of bytes as a structured type, and
33    /// to read and write the fields of that type as if the byte slice reference
34    /// were simply a reference to that type.
35    ///
36    /// ```rust
37    /// use zerocopy::*;
38    /// # use zerocopy_derive::*;
39    ///
40    /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)]
41    /// #[repr(C)]
42    /// struct UdpHeader {
43    ///     src_port: [u8; 2],
44    ///     dst_port: [u8; 2],
45    ///     length: [u8; 2],
46    ///     checksum: [u8; 2],
47    /// }
48    ///
49    /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)]
50    /// #[repr(C, packed)]
51    /// struct UdpPacket {
52    ///     header: UdpHeader,
53    ///     body: [u8],
54    /// }
55    ///
56    /// impl UdpPacket {
57    ///     pub fn parse<B: ByteSlice>(bytes: B) -> Option<Ref<B, UdpPacket>> {
58    ///         Ref::from_bytes(bytes).ok()
59    ///     }
60    /// }
61    /// ```
62    pub struct Ref<B, T: ?Sized> {
63        // INVARIANTS:
64        // - The referent (via `.deref`, `.deref_mut`, `.into`) byte slice is
65        //   aligned to `T`'s alignment, and its size is valid for `T`.
66        // - If `T: KnownLayout`, let `metadata` be
67        //   `T::PointerMetadata::from_elem_count` applied to `elem_count`.
68        //   Then `T::size_for_metadata(metadata)` is `Some(referent.len())`.
69        bytes: B,
70        // Ignored when `T` does not implement `KnownLayout`.
71        elem_count: usize,
72        _marker: PhantomData<T>,
73    }
74
75    impl<B, T> Ref<B, T> {
76        /// Constructs a new `Ref` to a sized `T`.
77        ///
78        /// # Safety
79        ///
80        /// `bytes` dereferences (via [`deref`], [`deref_mut`], and [`into`]) to
81        /// a byte slice which is aligned to `T`'s alignment and whose size is
82        /// `size_of::<T>()`.
83        ///
84        /// [`deref`]: core::ops::Deref::deref
85        /// [`deref_mut`]: core::ops::DerefMut::deref_mut
86        /// [`into`]: core::convert::Into::into
87        pub(super) unsafe fn new_sized_unchecked(bytes: B) -> Ref<B, T> {
88            // INVARIANTS: The caller has promised that `bytes`'s referent is
89            // validly aligned and has size `size_of::<T>()`. If `T:
90            // KnownLayout`, then, since `T` is sized, `T::PointerMetadata` is
91            // `()`. `from_elem_count` returns `()` for any element count, and
92            // `T::size_for_metadata(()) == Some(size_of::<T>())`. `size_of`
93            // reports this size in bytes [1].
94            //
95            // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of.html:
96            //
97            //     Returns the size of a type in bytes.
98            Ref { bytes, elem_count: 0, _marker: PhantomData }
99        }
100    }
101
102    impl<B, T: KnownLayout + ?Sized> Ref<B, T> {
103        /// Constructs a new `Ref`.
104        ///
105        /// # Safety
106        ///
107        /// `bytes` dereferences (via [`deref`], [`deref_mut`], and [`into`]) to
108        /// a byte slice which is aligned to `T`'s alignment and satisfies
109        /// `T::size_for_metadata(metadata) == Some(referent.len())`.
110        ///
111        /// [`deref`]: core::ops::Deref::deref
112        /// [`deref_mut`]: core::ops::DerefMut::deref_mut
113        /// [`into`]: core::convert::Into::into
114        pub(super) unsafe fn new_unchecked(bytes: B, metadata: T::PointerMetadata) -> Ref<B, T> {
115            // INVARIANTS: The caller has promised that `bytes`'s referent is
116            // validly aligned and has exactly the size described by `metadata`.
117            // `KnownLayout::PointerMetadata` is `()` for sized types and
118            // `usize` for slice DSTs. For both permitted metadata types,
119            // `from_elem_count(metadata.to_elem_count()) == metadata`: `()`
120            // round-trips through zero, while `usize` round-trips through
121            // itself. Thus, storing the element count preserves the metadata
122            // whose size the caller validated. This agrees with Rust's
123            // language-level definition of slice pointer metadata [1].
124            //
125            // [1] Per https://doc.rust-lang.org/1.56.0/reference/dynamically-sized-types.html:
126            //
127            //     Pointers to slices also store the number of elements of the
128            //     slice.
129            Ref { bytes, elem_count: metadata.to_elem_count(), _marker: PhantomData }
130        }
131
132        /// Gets the pointer metadata represented by this `Ref`.
133        #[inline(always)]
134        pub(super) fn pointer_metadata(&self) -> T::PointerMetadata {
135            // INVARIANTS: `KnownLayout::PointerMetadata` is either `()` or
136            // `usize`. For `()`, `from_elem_count` ignores the element count;
137            // for `usize`, it returns the element count unchanged.
138            T::PointerMetadata::from_elem_count(self.elem_count)
139        }
140    }
141
142    impl<B: ByteSlice, T: ?Sized> Ref<B, T> {
143        /// Access the byte slice as a [`ByteSlice`].
144        ///
145        /// # Safety
146        ///
147        /// The caller promises not to call methods on the returned
148        /// [`ByteSlice`] other than `ByteSlice` methods (for example, via
149        /// `Any::downcast_ref`).
150        ///
151        /// `as_byte_slice` promises to return a `ByteSlice` whose referent is
152        /// validly aligned for `T` and has a valid size for `T`. If `T:
153        /// KnownLayout`, then `T::size_for_metadata(self.pointer_metadata())`
154        /// returns `Some(referent.len())`.
155        pub(crate) unsafe fn as_byte_slice(&self) -> &impl ByteSlice {
156            // INVARIANTS: The caller promises not to call methods other than
157            // those on `ByteSlice`. Since `B: ByteSlice`, dereference stability
158            // guarantees that calling `ByteSlice` methods will not change the
159            // address or length of `self.bytes`'s referent.
160            //
161            // SAFETY: By invariant on `self`, the alignment, size, and metadata
162            // postconditions are upheld.
163            &self.bytes
164        }
165    }
166
167    impl<B: ByteSliceMut, T: ?Sized> Ref<B, T> {
168        /// Access the byte slice as a [`ByteSliceMut`].
169        ///
170        /// # Safety
171        ///
172        /// The caller promises not to call methods on the returned
173        /// [`ByteSliceMut`] other than `ByteSliceMut` methods (for example, via
174        /// `Any::downcast_mut`).
175        ///
176        /// `as_byte_slice_mut` promises to return a `ByteSliceMut` whose
177        /// referent is validly aligned for `T` and has a valid size for `T`. If
178        /// `T: KnownLayout`, then
179        /// `T::size_for_metadata(self.pointer_metadata())` returns
180        /// `Some(referent.len())`.
181        pub(crate) unsafe fn as_byte_slice_mut(&mut self) -> &mut impl ByteSliceMut {
182            // INVARIANTS: The caller promises not to call methods other than
183            // those on `ByteSliceMut`. Since `B: ByteSlice`, dereference
184            // stability guarantees that calling `ByteSlice` methods will not
185            // change the address or length of `self.bytes`'s referent.
186            //
187            // SAFETY: By invariant on `self`, the alignment, size, and metadata
188            // postconditions are upheld.
189            &mut self.bytes
190        }
191    }
192
193    impl<'a, B: IntoByteSlice<'a>, T: ?Sized> Ref<B, T> {
194        /// Access the byte slice as an [`IntoByteSlice`].
195        ///
196        /// # Safety
197        ///
198        /// The caller promises not to call methods on the returned
199        /// [`IntoByteSlice`] other than `IntoByteSlice` methods (for example,
200        /// via `Any::downcast_ref`).
201        ///
202        /// `into_byte_slice` promises to return an `IntoByteSlice` whose
203        /// referent is validly aligned for `T` and has a valid size for `T`. If
204        /// `T: KnownLayout`, then
205        /// `T::size_for_metadata(self.pointer_metadata())` returns
206        /// `Some(referent.len())`.
207        pub(crate) unsafe fn into_byte_slice(self) -> impl IntoByteSlice<'a> {
208            // INVARIANTS: The caller promises not to call methods other than
209            // those on `IntoByteSlice`. Since `B: ByteSlice`, dereference
210            // stability guarantees that calling `ByteSlice` methods will not
211            // change the address or length of `self.bytes`'s referent.
212            //
213            // SAFETY: By invariant on `self`, the alignment, size, and metadata
214            // postconditions are upheld.
215            self.bytes
216        }
217    }
218
219    impl<'a, B: IntoByteSliceMut<'a>, T: ?Sized> Ref<B, T> {
220        /// Access the byte slice as an [`IntoByteSliceMut`].
221        ///
222        /// # Safety
223        ///
224        /// The caller promises not to call methods on the returned
225        /// [`IntoByteSliceMut`] other than `IntoByteSliceMut` methods (for
226        /// example, via `Any::downcast_mut`).
227        ///
228        /// `into_byte_slice_mut` promises to return an `IntoByteSliceMut` whose
229        /// referent is validly aligned for `T` and has a valid size for `T`. If
230        /// `T: KnownLayout`, then
231        /// `T::size_for_metadata(self.pointer_metadata())` returns
232        /// `Some(referent.len())`.
233        pub(crate) unsafe fn into_byte_slice_mut(self) -> impl IntoByteSliceMut<'a> {
234            // INVARIANTS: The caller promises not to call methods other than
235            // those on `IntoByteSliceMut`. Since `B: ByteSlice`, dereference
236            // stability guarantees that calling `ByteSlice` methods will not
237            // change the address or length of `self.bytes`'s referent.
238            //
239            // SAFETY: By invariant on `self`, the alignment, size, and metadata
240            // postconditions are upheld.
241            self.bytes
242        }
243    }
244
245    impl<B: CloneableByteSlice + Clone, T: ?Sized> Clone for Ref<B, T> {
246        #[inline]
247        fn clone(&self) -> Ref<B, T> {
248            // INVARIANTS: Since `B: CloneableByteSlice`, `self.bytes.clone()` has
249            // the same address and length as `self.bytes`. We copy
250            // `self.elem_count`, so the clone also has the same metadata. Since
251            // `self` upholds the field invariants, so does the clone.
252            Ref { bytes: self.bytes.clone(), elem_count: self.elem_count, _marker: PhantomData }
253        }
254    }
255
256    // INVARIANTS: Since `B: CopyableByteSlice`, the copied `Ref`'s `bytes` has the
257    // same address and length as the original `Ref`'s `bytes`. The copied
258    // `elem_count` has the same metadata. Since the original upholds the field
259    // invariants, so does the copy.
260    impl<B: CopyableByteSlice + Copy, T: ?Sized> Copy for Ref<B, T> {}
261}
262
263#[allow(unreachable_pub)] // This is a false positive on our MSRV toolchain.
264pub use def::Ref;
265
266use crate::pointer::{
267    invariant::{Aligned, BecauseExclusive, Initialized, Safe, Unaligned},
268    BecauseRead, PtrInner,
269};
270
271impl<B, T> Ref<B, T>
272where
273    B: ByteSlice,
274{
275    #[must_use = "has no side effects"]
276    pub(crate) fn sized_from(bytes: B) -> Result<Ref<B, T>, CastError<B, T>> {
277        if bytes.len() != mem::size_of::<T>() {
278            return Err(SizeError::new(bytes).into());
279        }
280        if let Err(err) = util::validate_aligned_to::<_, T>(bytes.deref()) {
281            return Err(err.with_src(bytes).into());
282        }
283
284        // SAFETY: `size_of` returns `T`'s size in bytes [1]. The equality check
285        // above therefore establishes that `bytes` has exactly that byte
286        // length, and `validate_aligned_to` establishes alignment.
287        //
288        // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of.html:
289        //
290        //     Returns the size of a type in bytes.
291        Ok(unsafe { Ref::new_sized_unchecked(bytes) })
292    }
293}
294
295impl<B, T> Ref<B, T>
296where
297    B: SplitByteSlice,
298{
299    #[must_use = "has no side effects"]
300    pub(crate) fn sized_from_prefix(bytes: B) -> Result<(Ref<B, T>, B), CastError<B, T>> {
301        if bytes.len() < mem::size_of::<T>() {
302            return Err(SizeError::new(bytes).into());
303        }
304        if let Err(err) = util::validate_aligned_to::<_, T>(bytes.deref()) {
305            return Err(err.with_src(bytes).into());
306        }
307        let (bytes, suffix) = bytes.split_at(mem::size_of::<T>()).map_err(
308            #[inline(always)]
309            |b| SizeError::new(b).into(),
310        )?;
311        // SAFETY: We just validated alignment and that `bytes` is at least as
312        // large as `T`. `bytes.split_at(mem::size_of::<T>())?` ensures that the
313        // new `bytes` is exactly the size of `T`, measured in bytes as specified
314        // for `size_of` [1]. By safety postcondition on
315        // `SplitByteSlice::split_at` we can rely on `split_at` to produce the
316        // correct `bytes` and `suffix`.
317        //
318        // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of.html:
319        //
320        //     Returns the size of a type in bytes.
321        let r = unsafe { Ref::new_sized_unchecked(bytes) };
322        Ok((r, suffix))
323    }
324
325    #[must_use = "has no side effects"]
326    pub(crate) fn sized_from_suffix(bytes: B) -> Result<(B, Ref<B, T>), CastError<B, T>> {
327        let bytes_len = bytes.len();
328        let split_at = if let Some(split_at) = bytes_len.checked_sub(mem::size_of::<T>()) {
329            split_at
330        } else {
331            return Err(SizeError::new(bytes).into());
332        };
333        let (prefix, bytes) = bytes.split_at(split_at).map_err(|b| SizeError::new(b).into())?;
334        if let Err(err) = util::validate_aligned_to::<_, T>(bytes.deref()) {
335            return Err(err.with_src(bytes).into());
336        }
337        // SAFETY: Since `split_at` is defined as `bytes_len - size_of::<T>()`,
338        // the `bytes` which results from `let (prefix, bytes) =
339        // bytes.split_at(split_at)?` has length `size_of::<T>()`, measured in
340        // bytes as specified for `size_of` [1]. After constructing `bytes`, we
341        // validate that it has the proper alignment. By safety postcondition on
342        // `SplitByteSlice::split_at` we can rely on `split_at` to produce the
343        // correct `prefix` and `bytes`.
344        //
345        // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of.html:
346        //
347        //     Returns the size of a type in bytes.
348        let r = unsafe { Ref::new_sized_unchecked(bytes) };
349        Ok((prefix, r))
350    }
351}
352
353impl<B, T> Ref<B, T>
354where
355    B: ByteSlice,
356    T: KnownLayout + Immutable + ?Sized,
357{
358    /// Constructs a `Ref` from a byte slice.
359    ///
360    /// If the length of `source` is not a [valid size of `T`][valid-size], or
361    /// if `source` is not appropriately aligned for `T`, this returns `Err`. If
362    /// [`T: Unaligned`][t-unaligned], you can [infallibly discard the alignment
363    /// error][size-error-from].
364    ///
365    /// `T` may be a sized type, a slice, or a [slice DST][slice-dst].
366    ///
367    /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
368    /// [t-unaligned]: crate::Unaligned
369    /// [size-error-from]: error/struct.SizeError.html#method.from-1
370    /// [slice-dst]: KnownLayout#dynamically-sized-types
371    ///
372    /// # Compile-Time Assertions
373    ///
374    /// This method cannot yet be used on unsized types whose dynamically-sized
375    /// component is zero-sized. Attempting to use this method on such types
376    /// results in a compile-time assertion error; e.g.:
377    ///
378    /// ```compile_fail,E0080
379    /// use zerocopy::*;
380    /// # use zerocopy_derive::*;
381    ///
382    /// #[derive(Immutable, KnownLayout)]
383    /// #[repr(C)]
384    /// struct ZSTy {
385    ///     leading_sized: u16,
386    ///     trailing_dst: [()],
387    /// }
388    ///
389    /// let _ = Ref::<_, ZSTy>::from_bytes(&b"UU"[..]); // ⚠ Compile Error!
390    /// ```
391    ///
392    #[doc = codegen_section!(
393        header = "h5",
394        bench = "ref_type_from_bytes",
395        format = "coco",
396        arity = 3,
397        [
398            open
399            @index 1
400            @title "Sized"
401            @variant "static_size"
402        ],
403        [
404            @index 2
405            @title "Unsized"
406            @variant "dynamic_size"
407        ],
408        [
409            @index 3
410            @title "Dynamically Padded"
411            @variant "dynamic_padding"
412        ]
413    )]
414    #[must_use = "has no side effects"]
415    #[inline]
416    pub fn from_bytes(source: B) -> Result<Ref<B, T>, CastError<B, T>> {
417        static_assert_dst_is_not_zst!(T);
418        let metadata = match Ptr::from_ref(source.deref())
419            .try_cast_into_no_leftover::<T, BecauseImmutable>(None)
420        {
421            Ok(ptr) => T::pointer_to_metadata(ptr.as_inner().as_ptr()),
422            Err(e) => return Err(e.with_src(()).with_src(source)),
423        };
424        // SAFETY: By its safety postcondition, `try_cast_into_no_leftover`
425        // returned a `Ptr<T>` aligned as required for references [2], over the
426        // same byte range as `source.deref()`. `pointer_to_metadata` returns
427        // the metadata stored in that pointer, and `size_for_metadata` computes
428        // the corresponding dynamically-known byte size [1]. Thus,
429        // `T::size_for_metadata(metadata)` is `Some(source.len())`.
430        // `ByteSlice` and its applicable subtraits guarantee that the stored
431        // `source` continues to dereference or convert to that address and
432        // length. These facts establish both preconditions of `new_unchecked`.
433        //
434        // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of_val.html:
435        //
436        //     Returns the size of the pointed-to value in bytes.
437        //
438        //     ... when `T` has no statically-known size ... `size_of_val` can
439        //     be used to get the dynamically-known size.
440        //
441        // [2] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.align_of_val.html:
442        //
443        //     Returns the ABI-required minimum alignment of the type of the
444        //     value that `val` points to.
445        //
446        //     Every reference to a value of the type `T` must be a multiple of
447        //     this number.
448        Ok(unsafe { Ref::new_unchecked(source, metadata) })
449    }
450}
451
452impl<B, T> Ref<B, T>
453where
454    B: SplitByteSlice,
455    T: KnownLayout + Immutable + ?Sized,
456{
457    /// Constructs a `Ref` from the prefix of a byte slice.
458    ///
459    /// This method computes the [largest possible size of `T`][valid-size] that
460    /// can fit in the leading bytes of `source`, then attempts to return both a
461    /// `Ref` to those bytes, and a reference to the remaining bytes. If there
462    /// are insufficient bytes, or if `source` is not appropriately aligned,
463    /// this returns `Err`. If [`T: Unaligned`][t-unaligned], you can
464    /// [infallibly discard the alignment error][size-error-from].
465    ///
466    /// `T` may be a sized type, a slice, or a [slice DST][slice-dst].
467    ///
468    /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
469    /// [t-unaligned]: crate::Unaligned
470    /// [size-error-from]: error/struct.SizeError.html#method.from-1
471    /// [slice-dst]: KnownLayout#dynamically-sized-types
472    ///
473    /// # Compile-Time Assertions
474    ///
475    /// This method cannot yet be used on unsized types whose dynamically-sized
476    /// component is zero-sized. Attempting to use this method on such types
477    /// results in a compile-time assertion error; e.g.:
478    ///
479    /// ```compile_fail,E0080
480    /// use zerocopy::*;
481    /// # use zerocopy_derive::*;
482    ///
483    /// #[derive(Immutable, KnownLayout)]
484    /// #[repr(C)]
485    /// struct ZSTy {
486    ///     leading_sized: u16,
487    ///     trailing_dst: [()],
488    /// }
489    ///
490    /// let _ = Ref::<_, ZSTy>::from_prefix(&b"UU"[..]); // ⚠ Compile Error!
491    /// ```
492    ///
493    #[doc = codegen_section!(
494        header = "h5",
495        bench = "ref_type_from_prefix",
496        format = "coco",
497        arity = 3,
498        [
499            open
500            @index 1
501            @title "Sized"
502            @variant "static_size"
503        ],
504        [
505            @index 2
506            @title "Unsized"
507            @variant "dynamic_size"
508        ],
509        [
510            @index 3
511            @title "Dynamically Padded"
512            @variant "dynamic_padding"
513        ]
514    )]
515    #[must_use = "has no side effects"]
516    #[inline]
517    pub fn from_prefix(source: B) -> Result<(Ref<B, T>, B), CastError<B, T>> {
518        static_assert_dst_is_not_zst!(T);
519        let (metadata, remainder) = match Ptr::from_ref(source.deref())
520            .try_cast_into::<T, BecauseImmutable>(CastType::Prefix, None)
521        {
522            Ok((ptr, remainder)) => (T::pointer_to_metadata(ptr.as_inner().as_ptr()), remainder),
523            Err(e) => {
524                return Err(e.with_src(()).with_src(source));
525            }
526        };
527
528        // SAFETY: `remainder` is constructed as a subset of `source`, and so it
529        // cannot have a larger size than `source`. Both of their `len` methods
530        // measure bytes (`source` deref's to `[u8]`, and `remainder` is a
531        // `Ptr<[u8]>`), so `source.len() >= remainder.len()`. Thus, this cannot
532        // underflow.
533        #[allow(unstable_name_collisions)]
534        let split_at = unsafe { source.len().unchecked_sub(remainder.len()) };
535        let (bytes, suffix) = source.split_at(split_at).map_err(|b| SizeError::new(b).into())?;
536        // SAFETY: By its safety postcondition, `try_cast_into` returned an
537        // `Ptr<T>` aligned as required for references [2], and a remainder
538        // which are non-overlapping, cover `source.deref()`, and place the
539        // `Ptr<T>` at `source.deref()`'s address.
540        // Therefore, `split_at` is the typed pointer's byte length. By the
541        // safety postcondition of `SplitByteSlice::split_at`, `bytes` has that
542        // length and address. `pointer_to_metadata` returns the metadata stored
543        // in the typed pointer, and `size_for_metadata` computes the
544        // corresponding dynamically-known byte size [1]. Thus,
545        // `T::size_for_metadata(metadata)` is `Some(bytes.len())`. The
546        // `SplitByteSlice` and `ByteSlice` contracts preserve the established
547        // address and length, satisfying both preconditions of
548        // `new_unchecked`.
549        //
550        // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of_val.html:
551        //
552        //     Returns the size of the pointed-to value in bytes.
553        //
554        //     ... when `T` has no statically-known size ... `size_of_val` can
555        //     be used to get the dynamically-known size.
556        //
557        // [2] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.align_of_val.html:
558        //
559        //     Returns the ABI-required minimum alignment of the type of the
560        //     value that `val` points to.
561        //
562        //     Every reference to a value of the type `T` must be a multiple of
563        //     this number.
564        let r = unsafe { Ref::new_unchecked(bytes, metadata) };
565        Ok((r, suffix))
566    }
567
568    /// Constructs a `Ref` from the suffix of a byte slice.
569    ///
570    /// This method computes the [largest possible size of `T`][valid-size] that
571    /// can fit in the trailing bytes of `source`, then attempts to return both
572    /// a `Ref` to those bytes, and a reference to the preceding bytes. If there
573    /// are insufficient bytes, or if that suffix of `source` is not
574    /// appropriately aligned, this returns `Err`. If [`T:
575    /// Unaligned`][t-unaligned], you can [infallibly discard the alignment
576    /// error][size-error-from].
577    ///
578    /// `T` may be a sized type, a slice, or a [slice DST][slice-dst].
579    ///
580    /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
581    /// [t-unaligned]: crate::Unaligned
582    /// [size-error-from]: error/struct.SizeError.html#method.from-1
583    /// [slice-dst]: KnownLayout#dynamically-sized-types
584    ///
585    /// # Compile-Time Assertions
586    ///
587    /// This method cannot yet be used on unsized types whose dynamically-sized
588    /// component is zero-sized. Attempting to use this method on such types
589    /// results in a compile-time assertion error; e.g.:
590    ///
591    /// ```compile_fail,E0080
592    /// use zerocopy::*;
593    /// # use zerocopy_derive::*;
594    ///
595    /// #[derive(Immutable, KnownLayout)]
596    /// #[repr(C)]
597    /// struct ZSTy {
598    ///     leading_sized: u16,
599    ///     trailing_dst: [()],
600    /// }
601    ///
602    /// let _ = Ref::<_, ZSTy>::from_suffix(&b"UU"[..]); // ⚠ Compile Error!
603    /// ```
604    ///
605    #[doc = codegen_section!(
606        header = "h5",
607        bench = "ref_type_from_suffix",
608        format = "coco",
609        arity = 3,
610        [
611            open
612            @index 1
613            @title "Sized"
614            @variant "static_size"
615        ],
616        [
617            @index 2
618            @title "Unsized"
619            @variant "dynamic_size"
620        ],
621        [
622            @index 3
623            @title "Dynamically Padded"
624            @variant "dynamic_padding"
625        ]
626    )]
627    #[must_use = "has no side effects"]
628    #[inline]
629    pub fn from_suffix(source: B) -> Result<(B, Ref<B, T>), CastError<B, T>> {
630        static_assert_dst_is_not_zst!(T);
631        let (metadata, remainder) = match Ptr::from_ref(source.deref())
632            .try_cast_into::<T, BecauseImmutable>(CastType::Suffix, None)
633        {
634            Ok((ptr, remainder)) => (T::pointer_to_metadata(ptr.as_inner().as_ptr()), remainder),
635            Err(e) => {
636                let e = e.with_src(());
637                return Err(e.with_src(source));
638            }
639        };
640
641        let split_at = remainder.len();
642        let (prefix, bytes) = source.split_at(split_at).map_err(|b| SizeError::new(b).into())?;
643        // SAFETY: By its safety postcondition, `try_cast_into` returned an
644        // `Ptr<T>` aligned as required for references [2], and a remainder
645        // which are non-overlapping, cover `source.deref()`, and place the
646        // remainder at `source.deref()`'s address. More precisely,
647        // `PtrInner::try_cast_into` constructs the typed suffix from the
648        // `r_slice` produced by `split_at_unchecked(split_at)` and returns its
649        // `l_slice` as `remainder`. Thus, even when `T` is zero-sized, the typed
650        // pointer and the `bytes` produced by splitting `source` at
651        // `remainder.len()` have the same address and length. By the safety
652        // postcondition of `SplitByteSlice::split_at`, `bytes` retains that
653        // address and length. `pointer_to_metadata` returns the metadata stored
654        // in the typed pointer, and `size_for_metadata` computes the
655        // corresponding dynamically-known byte size [1]. Thus,
656        // `T::size_for_metadata(metadata)` is `Some(bytes.len())`. The
657        // `SplitByteSlice` and `ByteSlice` contracts preserve the established
658        // address and length, satisfying both preconditions of
659        // `new_unchecked`.
660        //
661        // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of_val.html:
662        //
663        //     Returns the size of the pointed-to value in bytes.
664        //
665        //     ... when `T` has no statically-known size ... `size_of_val` can
666        //     be used to get the dynamically-known size.
667        //
668        // [2] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.align_of_val.html:
669        //
670        //     Returns the ABI-required minimum alignment of the type of the
671        //     value that `val` points to.
672        //
673        //     Every reference to a value of the type `T` must be a multiple of
674        //     this number.
675        let r = unsafe { Ref::new_unchecked(bytes, metadata) };
676        Ok((prefix, r))
677    }
678}
679
680impl<B, T> Ref<B, T>
681where
682    B: ByteSlice,
683    T: KnownLayout<PointerMetadata = usize> + Immutable + ?Sized,
684{
685    /// Constructs a `Ref` from the given bytes with DST length equal to `count`
686    /// without copying.
687    ///
688    /// This method attempts to return a `Ref` to the prefix of `source`
689    /// interpreted as a `T` with `count` trailing elements, and a reference to
690    /// the remaining bytes. If the length of `source` is not equal to the size
691    /// of `Self` with `count` elements, or if `source` is not appropriately
692    /// aligned, this returns `Err`. If [`T: Unaligned`][t-unaligned], you can
693    /// [infallibly discard the alignment error][size-error-from].
694    ///
695    /// [t-unaligned]: crate::Unaligned
696    /// [size-error-from]: error/struct.SizeError.html#method.from-1
697    ///
698    /// # Compile-Time Assertions
699    ///
700    /// This method cannot yet be used on unsized types whose dynamically-sized
701    /// component is zero-sized. Attempting to use this method on such types
702    /// results in a compile-time assertion error; e.g.:
703    ///
704    /// ```compile_fail,E0080
705    /// use zerocopy::*;
706    /// # use zerocopy_derive::*;
707    ///
708    /// #[derive(Immutable, KnownLayout)]
709    /// #[repr(C)]
710    /// struct ZSTy {
711    ///     leading_sized: u16,
712    ///     trailing_dst: [()],
713    /// }
714    ///
715    /// let _ = Ref::<_, ZSTy>::from_bytes_with_elems(&b"UU"[..], 42); // ⚠ Compile Error!
716    /// ```
717    ///
718    #[doc = codegen_section!(
719        header = "h5",
720        bench = "ref_type_from_bytes_with_elems",
721        format = "coco",
722        arity = 2,
723        [
724            open
725            @index 1
726            @title "Unsized"
727            @variant "dynamic_size"
728        ],
729        [
730            @index 2
731            @title "Dynamically Padded"
732            @variant "dynamic_padding"
733        ]
734    )]
735    #[inline]
736    pub fn from_bytes_with_elems(source: B, count: usize) -> Result<Ref<B, T>, CastError<B, T>> {
737        static_assert_dst_is_not_zst!(T);
738        let expected_len = match T::size_for_metadata(count) {
739            Some(len) => len,
740            None => return Err(SizeError::new(source).into()),
741        };
742        if source.len() != expected_len {
743            return Err(SizeError::new(source).into());
744        }
745        if let Err(e) = Ptr::from_ref(source.deref())
746            .try_cast_into_no_leftover::<T, BecauseImmutable>(Some(count))
747        {
748            return Err(e.with_src(()).with_src(source));
749        }
750        // SAFETY: `size_for_metadata(count)` returned `expected_len`, and the
751        // equality check established that this is `source.len()`. This is the
752        // dynamically-known byte size described by `size_of_val` [1]. By its
753        // safety postcondition, `try_cast_into_no_leftover(Some(count))` only
754        // succeeded after producing a `Ptr<T>` aligned as required for
755        // references [2], with that metadata over the same byte range as
756        // `source.deref()`. `ByteSlice` and its applicable subtraits guarantee
757        // that the stored `source` continues to dereference or convert to that
758        // address and length. These facts establish both preconditions of
759        // `new_unchecked`.
760        //
761        // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of_val.html:
762        //
763        //     Returns the size of the pointed-to value in bytes.
764        //
765        //     ... when `T` has no statically-known size ... `size_of_val` can
766        //     be used to get the dynamically-known size.
767        //
768        // [2] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.align_of_val.html:
769        //
770        //     Returns the ABI-required minimum alignment of the type of the
771        //     value that `val` points to.
772        //
773        //     Every reference to a value of the type `T` must be a multiple of
774        //     this number.
775        Ok(unsafe { Ref::new_unchecked(source, count) })
776    }
777}
778
779impl<B, T> Ref<B, T>
780where
781    B: SplitByteSlice,
782    T: KnownLayout<PointerMetadata = usize> + Immutable + ?Sized,
783{
784    /// Constructs a `Ref` from the prefix of the given bytes with DST
785    /// length equal to `count` without copying.
786    ///
787    /// This method attempts to return a `Ref` to the prefix of `source`
788    /// interpreted as a `T` with `count` trailing elements, and a reference to
789    /// the remaining bytes. If there are insufficient bytes, or if `source` is
790    /// not appropriately aligned, this returns `Err`. If [`T:
791    /// Unaligned`][t-unaligned], you can [infallibly discard the alignment
792    /// error][size-error-from].
793    ///
794    /// [t-unaligned]: crate::Unaligned
795    /// [size-error-from]: error/struct.SizeError.html#method.from-1
796    ///
797    /// # Compile-Time Assertions
798    ///
799    /// This method cannot yet be used on unsized types whose dynamically-sized
800    /// component is zero-sized. Attempting to use this method on such types
801    /// results in a compile-time assertion error; e.g.:
802    ///
803    /// ```compile_fail,E0080
804    /// use zerocopy::*;
805    /// # use zerocopy_derive::*;
806    ///
807    /// #[derive(Immutable, KnownLayout)]
808    /// #[repr(C)]
809    /// struct ZSTy {
810    ///     leading_sized: u16,
811    ///     trailing_dst: [()],
812    /// }
813    ///
814    /// let _ = Ref::<_, ZSTy>::from_prefix_with_elems(&b"UU"[..], 42); // ⚠ Compile Error!
815    /// ```
816    ///
817    #[doc = codegen_section!(
818        header = "h5",
819        bench = "ref_type_from_prefix_with_elems",
820        format = "coco",
821        arity = 2,
822        [
823            open
824            @index 1
825            @title "Unsized"
826            @variant "dynamic_size"
827        ],
828        [
829            @index 2
830            @title "Dynamically Padded"
831            @variant "dynamic_padding"
832        ]
833    )]
834    #[inline]
835    pub fn from_prefix_with_elems(
836        source: B,
837        count: usize,
838    ) -> Result<(Ref<B, T>, B), CastError<B, T>> {
839        static_assert_dst_is_not_zst!(T);
840        let expected_len = match T::size_for_metadata(count) {
841            Some(len) => len,
842            None => return Err(SizeError::new(source).into()),
843        };
844        let (prefix, bytes) = source.split_at(expected_len).map_err(SizeError::new)?;
845        Self::from_bytes_with_elems(prefix, count).map(move |l| (l, bytes))
846    }
847
848    /// Constructs a `Ref` from the suffix of the given bytes with DST length
849    /// equal to `count` without copying.
850    ///
851    /// This method attempts to return a `Ref` to the suffix of `source`
852    /// interpreted as a `T` with `count` trailing elements, and a reference to
853    /// the preceding bytes. If there are insufficient bytes, or if that suffix
854    /// of `source` is not appropriately aligned, this returns `Err`. If [`T:
855    /// Unaligned`][t-unaligned], you can [infallibly discard the alignment
856    /// error][size-error-from].
857    ///
858    /// [t-unaligned]: crate::Unaligned
859    /// [size-error-from]: error/struct.SizeError.html#method.from-1
860    ///
861    /// # Compile-Time Assertions
862    ///
863    /// This method cannot yet be used on unsized types whose dynamically-sized
864    /// component is zero-sized. Attempting to use this method on such types
865    /// results in a compile-time assertion error; e.g.:
866    ///
867    /// ```compile_fail,E0080
868    /// use zerocopy::*;
869    /// # use zerocopy_derive::*;
870    ///
871    /// #[derive(Immutable, KnownLayout)]
872    /// #[repr(C)]
873    /// struct ZSTy {
874    ///     leading_sized: u16,
875    ///     trailing_dst: [()],
876    /// }
877    ///
878    /// let _ = Ref::<_, ZSTy>::from_suffix_with_elems(&b"UU"[..], 42); // ⚠ Compile Error!
879    /// ```
880    ///
881    #[doc = codegen_section!(
882        header = "h5",
883        bench = "ref_type_from_suffix_with_elems",
884        format = "coco",
885        arity = 2,
886        [
887            open
888            @index 1
889            @title "Unsized"
890            @variant "dynamic_size"
891        ],
892        [
893            @index 2
894            @title "Dynamically Padded"
895            @variant "dynamic_padding"
896        ]
897    )]
898    #[inline]
899    pub fn from_suffix_with_elems(
900        source: B,
901        count: usize,
902    ) -> Result<(B, Ref<B, T>), CastError<B, T>> {
903        static_assert_dst_is_not_zst!(T);
904        let expected_len = match T::size_for_metadata(count) {
905            Some(len) => len,
906            None => return Err(SizeError::new(source).into()),
907        };
908        let split_at = if let Some(split_at) = source.len().checked_sub(expected_len) {
909            split_at
910        } else {
911            return Err(SizeError::new(source).into());
912        };
913        // SAFETY: The preceding `source.len().checked_sub(expected_len)`
914        // guarantees that `split_at` is in-bounds.
915        let (bytes, suffix) = unsafe { source.split_at_unchecked(split_at) };
916        Self::from_bytes_with_elems(suffix, count).map(move |l| (bytes, l))
917    }
918}
919
920impl<'a, B, T> Ref<B, T>
921where
922    B: 'a + IntoByteSlice<'a>,
923    T: FromBytes + KnownLayout + Immutable + ?Sized,
924{
925    /// Converts this `Ref` into a reference.
926    ///
927    /// `into_ref` consumes the `Ref`, and returns a reference to `T`.
928    ///
929    /// Note: this is an associated function, which means that you have to call
930    /// it as `Ref::into_ref(r)` instead of `r.into_ref()`. This is so that
931    /// there is no conflict with a method on the inner type.
932    ///
933    #[doc = codegen_section!(
934        header = "h5",
935        bench = "ref_type_into_ref",
936        format = "coco",
937        arity = 3,
938        [
939            open
940            @index 1
941            @title "Sized"
942            @variant "static_size"
943        ],
944        [
945            @index 2
946            @title "Unsized"
947            @variant "dynamic_size"
948        ],
949        [
950            @index 3
951            @title "Dynamically Padded"
952            @variant "dynamic_padding"
953        ]
954    )]
955    #[must_use = "has no side effects"]
956    #[inline(always)]
957    pub fn into_ref(r: Self) -> &'a T {
958        // Presumably unreachable, since we've guarded each constructor of `Ref`.
959        static_assert_dst_is_not_zst!(T);
960
961        let metadata = r.pointer_metadata();
962
963        // SAFETY: We don't call any methods on `b` other than those provided by
964        // `IntoByteSlice`.
965        let b = unsafe { r.into_byte_slice() };
966        let b = b.into_byte_slice();
967
968        if let crate::layout::SizeInfo::Sized { .. } = T::LAYOUT.size_info {
969            let ptr = Ptr::from_ref(b);
970            // SAFETY: We just checked that `T: Sized`. By invariant on `r`,
971            // `b`'s size is equal to `size_of::<T>()`.
972            let ptr = unsafe { cast_for_sized::<T, _, _, _>(ptr) };
973
974            // SAFETY: None of the preceding transformations modifies the
975            // address of the pointer, and by invariant on `r`, we know that it
976            // is validly-aligned.
977            let ptr = unsafe { ptr.assume_alignment::<Aligned>() };
978            return ptr.as_ref();
979        }
980
981        // PANICS: By post-condition on `into_byte_slice`, `b` is aligned for
982        // `T`, and its size is exactly the size encoded by `metadata`. By
983        // post-condition, `b.into_byte_slice()` produces a byte slice with
984        // identical address and length to that produced by `b.deref()`.
985        let ptr = Ptr::from_ref(b.into_byte_slice())
986            .try_cast_into_no_leftover::<T, BecauseImmutable>(Some(metadata))
987            .expect("zerocopy internal error: into_ref should be infallible");
988        let ptr = ptr.recall_validity();
989        ptr.as_ref()
990    }
991}
992
993impl<'a, B, T> Ref<B, T>
994where
995    B: 'a + IntoByteSliceMut<'a>,
996    T: FromBytes + IntoBytes + KnownLayout + ?Sized,
997{
998    /// Converts this `Ref` into a mutable reference.
999    ///
1000    /// `into_mut` consumes the `Ref`, and returns a mutable reference to `T`.
1001    ///
1002    /// Note: this is an associated function, which means that you have to call
1003    /// it as `Ref::into_mut(r)` instead of `r.into_mut()`. This is so that
1004    /// there is no conflict with a method on the inner type.
1005    ///
1006    #[doc = codegen_section!(
1007        header = "h5",
1008        bench = "ref_type_into_mut",
1009        format = "coco",
1010        arity = 2,
1011        [
1012            open
1013            @index 1
1014            @title "Sized"
1015            @variant "static_size"
1016        ],
1017        [
1018            @index 2
1019            @title "Unsized"
1020            @variant "dynamic_size"
1021        ]
1022    )]
1023    #[must_use = "has no side effects"]
1024    #[inline(always)]
1025    pub fn into_mut(r: Self) -> &'a mut T {
1026        // Presumably unreachable, since we've guarded each constructor of `Ref`.
1027        static_assert_dst_is_not_zst!(T);
1028
1029        let metadata = r.pointer_metadata();
1030
1031        // SAFETY: We don't call any methods on `b` other than those provided by
1032        // `IntoByteSliceMut`.
1033        let b = unsafe { r.into_byte_slice_mut() };
1034        let b = b.into_byte_slice_mut();
1035
1036        if let crate::layout::SizeInfo::Sized { .. } = T::LAYOUT.size_info {
1037            let ptr = Ptr::from_mut(b);
1038            // SAFETY: We just checked that `T: Sized`. By invariant on `r`,
1039            // `b`'s size is equal to `size_of::<T>()`.
1040            let ptr = unsafe {
1041                cast_for_sized::<
1042                    T,
1043                    _,
1044                    (BecauseRead, BecauseExclusive),
1045                    (BecauseMutationCompatible, BecauseSharedCompatible),
1046                >(ptr)
1047            };
1048
1049            // SAFETY: None of the preceding transformations modifies the
1050            // address of the pointer, and by invariant on `r`, we know that it
1051            // is validly-aligned.
1052            let ptr = unsafe { ptr.assume_alignment::<Aligned>() };
1053            return ptr.as_mut();
1054        }
1055
1056        // PANICS: By post-condition on `into_byte_slice_mut`, `b` is aligned
1057        // for `T`, and its size is exactly the size encoded by `metadata`. By
1058        // post-condition, `b.into_byte_slice_mut()` produces a byte slice with
1059        // identical address and length to that produced by `b.deref_mut()`.
1060        let ptr = Ptr::from_mut(b.into_byte_slice_mut())
1061            .try_cast_into_no_leftover::<T, BecauseExclusive>(Some(metadata))
1062            .expect("zerocopy internal error: into_mut should be infallible");
1063        let ptr = ptr.recall_validity::<_, (_, (_, _))>();
1064        ptr.as_mut()
1065    }
1066}
1067
1068impl<B, T> Ref<B, T>
1069where
1070    B: ByteSlice,
1071    T: ?Sized,
1072{
1073    /// Gets the underlying bytes.
1074    ///
1075    /// Note: this is an associated function, which means that you have to call
1076    /// it as `Ref::bytes(r)` instead of `r.bytes()`. This is so that there is
1077    /// no conflict with a method on the inner type.
1078    ///
1079    #[doc = codegen_section!(
1080        header = "h5",
1081        bench = "ref_type_bytes",
1082        format = "coco",
1083        arity = 3,
1084        [
1085            open
1086            @index 1
1087            @title "Sized"
1088            @variant "static_size"
1089        ],
1090        [
1091            @index 2
1092            @title "Unsized"
1093            @variant "dynamic_size"
1094        ],
1095        [
1096            @index 3
1097            @title "Dynamically Padded"
1098            @variant "dynamic_padding"
1099        ]
1100    )]
1101    #[inline]
1102    pub fn bytes(r: &Self) -> &[u8] {
1103        // SAFETY: We don't call any methods on `b` other than those provided by
1104        // `ByteSlice`.
1105        unsafe { r.as_byte_slice().deref() }
1106    }
1107}
1108
1109impl<B, T> Ref<B, T>
1110where
1111    B: ByteSliceMut,
1112    T: ?Sized,
1113{
1114    /// Gets the underlying bytes mutably.
1115    ///
1116    /// Note: this is an associated function, which means that you have to call
1117    /// it as `Ref::bytes_mut(r)` instead of `r.bytes_mut()`. This is so that
1118    /// there is no conflict with a method on the inner type.
1119    ///
1120    #[doc = codegen_section!(
1121        header = "h5",
1122        bench = "ref_type_bytes_mut",
1123        format = "coco",
1124        arity = 3,
1125        [
1126            open
1127            @index 1
1128            @title "Sized"
1129            @variant "static_size"
1130        ],
1131        [
1132            @index 2
1133            @title "Unsized"
1134            @variant "dynamic_size"
1135        ],
1136        [
1137            @index 3
1138            @title "Dynamically Padded"
1139            @variant "dynamic_padding"
1140        ]
1141    )]
1142    #[inline]
1143    pub fn bytes_mut(r: &mut Self) -> &mut [u8] {
1144        // SAFETY: We don't call any methods on `b` other than those provided by
1145        // `ByteSliceMut`.
1146        unsafe { r.as_byte_slice_mut().deref_mut() }
1147    }
1148}
1149
1150impl<B, T> Ref<B, T>
1151where
1152    B: ByteSlice,
1153    T: FromBytes,
1154{
1155    /// Reads a copy of `T`.
1156    ///
1157    /// Note: this is an associated function, which means that you have to call
1158    /// it as `Ref::read(r)` instead of `r.read()`. This is so that there is no
1159    /// conflict with a method on the inner type.
1160    ///
1161    #[doc = codegen_section!(
1162        header = "h5",
1163        bench = "ref_type_read_static_size",
1164        format = "coco_static_size",
1165    )]
1166    #[must_use = "has no side effects"]
1167    #[inline]
1168    pub fn read(r: &Self) -> T {
1169        // SAFETY: We don't call any methods on `b` other than those provided by
1170        // `ByteSlice`.
1171        let b = unsafe { r.as_byte_slice() };
1172
1173        // SAFETY: By postcondition on `as_byte_slice`, we know that `b` is a
1174        // valid size and alignment for `T`. By safety invariant on `ByteSlice`,
1175        // we know that this is preserved via `.deref()`. Because `T:
1176        // FromBytes`, it is sound to interpret these bytes as a `T`.
1177        unsafe { ptr::read(b.deref().as_ptr().cast::<T>()) }
1178    }
1179}
1180
1181impl<B, T> Ref<B, T>
1182where
1183    B: ByteSliceMut,
1184    T: IntoBytes,
1185{
1186    /// Writes the bytes of `t` and then forgets `t`.
1187    ///
1188    /// Note: this is an associated function, which means that you have to call
1189    /// it as `Ref::write(r, t)` instead of `r.write(t)`. This is so that there
1190    /// is no conflict with a method on the inner type.
1191    ///
1192    #[doc = codegen_section!(
1193        header = "h5",
1194        bench = "ref_type_write_static_size",
1195        format = "coco_static_size",
1196    )]
1197    #[inline]
1198    pub fn write(r: &mut Self, t: T) {
1199        // SAFETY: We don't call any methods on `b` other than those provided by
1200        // `ByteSliceMut`.
1201        let b = unsafe { r.as_byte_slice_mut() };
1202
1203        // SAFETY: By postcondition on `as_byte_slice_mut`, we know that `b` is a
1204        // valid size and alignment for `T`. By safety invariant on
1205        // `ByteSlice`, we know that this is preserved via `.deref()`. Writing
1206        // `t` to the buffer will allow all of the bytes of `t` to be accessed
1207        // as a `[u8]`, but because `T: IntoBytes`, we know that this is sound.
1208        unsafe { ptr::write(b.deref_mut().as_mut_ptr().cast::<T>(), t) }
1209    }
1210}
1211
1212impl<B, T> Deref for Ref<B, T>
1213where
1214    B: ByteSlice,
1215    T: FromBytes + KnownLayout + Immutable + ?Sized,
1216{
1217    type Target = T;
1218
1219    /// Dereferences the value.
1220    ///
1221    #[doc = codegen_section!(
1222        header = "h5",
1223        bench = "ref_type_deref",
1224        format = "coco",
1225        arity = 3,
1226        [
1227            open
1228            @index 1
1229            @title "Sized"
1230            @variant "static_size"
1231        ],
1232        [
1233            @index 2
1234            @title "Unsized"
1235            @variant "dynamic_size"
1236        ],
1237        [
1238            @index 3
1239            @title "Dynamically Padded"
1240            @variant "dynamic_padding"
1241        ]
1242    )]
1243    #[inline]
1244    fn deref(&self) -> &T {
1245        // Presumably unreachable, since we've guarded each constructor of `Ref`.
1246        static_assert_dst_is_not_zst!(T);
1247
1248        let metadata = self.pointer_metadata();
1249
1250        // SAFETY: We don't call any methods on `b` other than those provided by
1251        // `ByteSlice`.
1252        let b = unsafe { self.as_byte_slice() };
1253        let b = b.deref();
1254
1255        if let crate::layout::SizeInfo::Sized { .. } = T::LAYOUT.size_info {
1256            let ptr = Ptr::from_ref(b);
1257            // SAFETY: We just checked that `T: Sized`. By invariant on `r`,
1258            // `b`'s size is equal to `size_of::<T>()`.
1259            let ptr = unsafe { cast_for_sized::<T, _, _, _>(ptr) };
1260
1261            // SAFETY: None of the preceding transformations modifies the
1262            // address of the pointer, and by invariant on `r`, we know that it
1263            // is validly-aligned.
1264            let ptr = unsafe { ptr.assume_alignment::<Aligned>() };
1265            return ptr.as_ref();
1266        }
1267
1268        // PANICS: By postcondition on `as_byte_slice`, `b` is aligned for `T`,
1269        // and its size is exactly the size encoded by `metadata`. By invariant
1270        // on `ByteSlice`, these are preserved through `.deref()`, so this
1271        // `unwrap` will not panic.
1272        let ptr = Ptr::from_ref(b)
1273            .try_cast_into_no_leftover::<T, BecauseImmutable>(Some(metadata))
1274            .expect("zerocopy internal error: Deref::deref should be infallible");
1275        let ptr = ptr.recall_validity();
1276        ptr.as_ref()
1277    }
1278}
1279
1280impl<B, T> DerefMut for Ref<B, T>
1281where
1282    B: ByteSliceMut,
1283    // FIXME(#251): We can't remove `Immutable` here because it's required by
1284    // the impl of `Deref`, which is a super-trait of `DerefMut`. Maybe we can
1285    // add a separate inherent method for this?
1286    T: FromBytes + IntoBytes + KnownLayout + Immutable + ?Sized,
1287{
1288    /// Mutably dereferences the value.
1289    ///
1290    #[doc = codegen_section!(
1291        header = "h5",
1292        bench = "ref_type_deref_mut",
1293        format = "coco",
1294        arity = 2,
1295        [
1296            open
1297            @index 1
1298            @title "Sized"
1299            @variant "static_size"
1300        ],
1301        [
1302            @index 2
1303            @title "Unsized"
1304            @variant "dynamic_size"
1305        ]
1306    )]
1307    #[inline]
1308    fn deref_mut(&mut self) -> &mut T {
1309        // Presumably unreachable, since we've guarded each constructor of `Ref`.
1310        static_assert_dst_is_not_zst!(T);
1311
1312        let metadata = self.pointer_metadata();
1313
1314        // SAFETY: We don't call any methods on `b` other than those provided by
1315        // `ByteSliceMut`.
1316        let b = unsafe { self.as_byte_slice_mut() };
1317        let b = b.deref_mut();
1318
1319        if let crate::layout::SizeInfo::Sized { .. } = T::LAYOUT.size_info {
1320            let ptr = Ptr::from_mut(b);
1321            // SAFETY: We just checked that `T: Sized`. By invariant on `r`,
1322            // `b`'s size is equal to `size_of::<T>()`.
1323            let ptr = unsafe {
1324                cast_for_sized::<
1325                    T,
1326                    _,
1327                    (BecauseRead, BecauseExclusive),
1328                    (BecauseMutationCompatible, BecauseSharedCompatible),
1329                >(ptr)
1330            };
1331
1332            // SAFETY: None of the preceding transformations modifies the
1333            // address of the pointer, and by invariant on `r`, we know that it
1334            // is validly-aligned.
1335            let ptr = unsafe { ptr.assume_alignment::<Aligned>() };
1336            return ptr.as_mut();
1337        }
1338
1339        // PANICS: By postcondition on `as_byte_slice_mut`, `b` is aligned for
1340        // `T`, and its size is exactly the size encoded by `metadata`. By
1341        // invariant on `ByteSlice`, these are preserved through `.deref_mut()`,
1342        // so this `unwrap` will not panic.
1343        let ptr = Ptr::from_mut(b)
1344            .try_cast_into_no_leftover::<T, BecauseExclusive>(Some(metadata))
1345            .expect("zerocopy internal error: DerefMut::deref_mut should be infallible");
1346        let ptr = ptr.recall_validity::<_, (_, (_, BecauseExclusive))>();
1347        ptr.as_mut()
1348    }
1349}
1350
1351impl<T, B> Display for Ref<B, T>
1352where
1353    B: ByteSlice,
1354    T: FromBytes + Display + KnownLayout + Immutable + ?Sized,
1355{
1356    #[inline]
1357    fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1358        let inner: &T = self;
1359        inner.fmt(fmt)
1360    }
1361}
1362
1363impl<T, B> Debug for Ref<B, T>
1364where
1365    B: ByteSlice,
1366    T: FromBytes + Debug + KnownLayout + Immutable + ?Sized,
1367{
1368    #[inline]
1369    fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1370        let inner: &T = self;
1371        fmt.debug_tuple("Ref").field(&inner).finish()
1372    }
1373}
1374
1375impl<T, B> Eq for Ref<B, T>
1376where
1377    B: ByteSlice,
1378    T: FromBytes + Eq + KnownLayout + Immutable + ?Sized,
1379{
1380}
1381
1382impl<T, B> PartialEq for Ref<B, T>
1383where
1384    B: ByteSlice,
1385    T: FromBytes + PartialEq + KnownLayout + Immutable + ?Sized,
1386{
1387    #[inline]
1388    fn eq(&self, other: &Self) -> bool {
1389        self.deref().eq(other.deref())
1390    }
1391}
1392
1393impl<T, B> Ord for Ref<B, T>
1394where
1395    B: ByteSlice,
1396    T: FromBytes + Ord + KnownLayout + Immutable + ?Sized,
1397{
1398    #[inline]
1399    fn cmp(&self, other: &Self) -> Ordering {
1400        let inner: &T = self;
1401        let other_inner: &T = other;
1402        inner.cmp(other_inner)
1403    }
1404}
1405
1406impl<T, B> PartialOrd for Ref<B, T>
1407where
1408    B: ByteSlice,
1409    T: FromBytes + PartialOrd + KnownLayout + Immutable + ?Sized,
1410{
1411    #[inline]
1412    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1413        let inner: &T = self;
1414        let other_inner: &T = other;
1415        inner.partial_cmp(other_inner)
1416    }
1417}
1418
1419/// # Safety
1420///
1421/// `T: Sized` and `ptr`'s referent must have size `size_of::<T>()`.
1422#[inline(always)]
1423unsafe fn cast_for_sized<'a, T, A, R, S>(
1424    ptr: Ptr<'a, [u8], (A, Aligned, Safe)>,
1425) -> Ptr<'a, T, (A, Unaligned, Safe)>
1426where
1427    T: FromBytes + KnownLayout + ?Sized,
1428    A: crate::invariant::Aliasing,
1429    [u8]: MutationCompatible<T, A, Initialized, Initialized, R>,
1430    T: TransmuteFromPtr<T, A, Initialized, Safe, crate::pointer::cast::IdCast, S>,
1431{
1432    use crate::pointer::cast::{Cast, Project};
1433
1434    enum CastForSized {}
1435
1436    // SAFETY: `CastForSized` is only used below with the input `ptr`, which the
1437    // caller promises has size `size_of::<T>()`. Thus, the referent produced in
1438    // this cast has the same size as `ptr`'s referent. All operations preserve
1439    // provenance.
1440    unsafe impl<T: ?Sized + KnownLayout> Project<[u8], T> for CastForSized {
1441        #[inline(always)]
1442        fn project(src: PtrInner<'_, [u8]>) -> *mut T {
1443            T::raw_from_ptr_len(
1444                src.as_non_null().cast(),
1445                <T::PointerMetadata as crate::PointerMetadata>::from_elem_count(0),
1446            )
1447            .as_ptr()
1448        }
1449    }
1450
1451    // SAFETY: The `Project::project` impl preserves referent address.
1452    unsafe impl<T: ?Sized + KnownLayout> Cast<[u8], T> for CastForSized {}
1453
1454    ptr.recall_validity::<Initialized, (_, (_, _))>()
1455        .cast::<_, CastForSized, _>()
1456        .recall_validity::<Safe, _>()
1457}
1458
1459#[cfg(test)]
1460#[allow(clippy::assertions_on_result_states)]
1461mod tests {
1462    use core::convert::TryInto as _;
1463
1464    use super::*;
1465    use crate::util::testutil::*;
1466
1467    #[test]
1468    fn test_mut_slice_into_ref() {
1469        // Prior to #1260/#1299, calling `into_ref` on a `&mut [u8]`-backed
1470        // `Ref` was not supported.
1471        let mut buf = [0u8];
1472        let r = Ref::<&mut [u8], u8>::from_bytes(&mut buf).unwrap();
1473        assert_eq!(Ref::into_ref(r), &0);
1474    }
1475
1476    #[test]
1477    fn test_address() {
1478        // Test that the `Deref` and `DerefMut` implementations return a
1479        // reference which points to the right region of memory.
1480
1481        let buf = [0];
1482        let r = Ref::<_, u8>::from_bytes(&buf[..]).unwrap();
1483        let buf_ptr = buf.as_ptr();
1484        let deref_ptr: *const u8 = r.deref();
1485        assert_eq!(buf_ptr, deref_ptr);
1486
1487        let buf = [0];
1488        let r = Ref::<_, [u8]>::from_bytes(&buf[..]).unwrap();
1489        let buf_ptr = buf.as_ptr();
1490        let deref_ptr = r.deref().as_ptr();
1491        assert_eq!(buf_ptr, deref_ptr);
1492    }
1493
1494    #[test]
1495    #[allow(clippy::clone_on_copy)] // Exercise `Ref`'s manual `Clone` impl.
1496    fn test_with_elems_preserves_ambiguous_metadata() {
1497        #[derive(FromBytes, Immutable, KnownLayout)]
1498        #[repr(C, align(8))]
1499        struct Frame {
1500            header: [u8; 8],
1501            body: [u8],
1502        }
1503
1504        #[derive(FromBytes, Immutable, KnownLayout)]
1505        #[repr(C, align(8))]
1506        struct OddHeader {
1507            header: [u8; 7],
1508            body: [u8],
1509        }
1510
1511        // Dynamic trailing padding makes these pairs of distinct element
1512        // counts produce the same total byte size. Thus, the byte length alone
1513        // cannot recover the count supplied to a `*_with_elems` constructor.
1514        assert_eq!(Frame::size_for_metadata(1), Some(16));
1515        assert_eq!(Frame::size_for_metadata(8), Some(16));
1516        assert_eq!(OddHeader::size_for_metadata(0), Some(8));
1517        assert_eq!(OddHeader::size_for_metadata(1), Some(8));
1518
1519        let bytes = Align::<[u8; 32], AU64>::default();
1520
1521        let whole = Ref::<_, Frame>::from_bytes_with_elems(&bytes.t[..16], 1).unwrap();
1522        assert_eq!(whole.body.len(), 1);
1523        assert_eq!(Ref::bytes(&whole).len(), 16);
1524        assert_eq!(whole.clone().body.len(), 1);
1525        let copied = whole;
1526        assert_eq!(copied.body.len(), 1);
1527        assert_eq!(Ref::into_ref(whole).body.len(), 1);
1528
1529        let (prefix, rest) = Ref::<_, Frame>::from_prefix_with_elems(&bytes.t[..], 1).unwrap();
1530        assert_eq!(prefix.body.len(), 1);
1531        assert_eq!(rest.len(), 16);
1532
1533        let (before, suffix) = Ref::<_, Frame>::from_suffix_with_elems(&bytes.t[..24], 1).unwrap();
1534        assert_eq!(before.len(), 8);
1535        assert_eq!(suffix.body.len(), 1);
1536
1537        // Zero is real metadata, not a sentinel for "infer from the bytes".
1538        let empty = Ref::<_, OddHeader>::from_bytes_with_elems(&bytes.t[..8], 0).unwrap();
1539        assert!(empty.body.is_empty());
1540        assert!(Ref::into_ref(empty).body.is_empty());
1541
1542        // The implicit constructors still choose the largest fitting count,
1543        // and retain the metadata selected during their validating cast.
1544        let inferred = Ref::<_, Frame>::from_bytes(&bytes.t[..16]).unwrap();
1545        assert_eq!(inferred.body.len(), 8);
1546        let (inferred, rest) = Ref::<_, Frame>::from_prefix(&bytes.t[..16]).unwrap();
1547        assert_eq!(inferred.body.len(), 8);
1548        assert!(rest.is_empty());
1549        let (before, inferred) = Ref::<_, Frame>::from_suffix(&bytes.t[..16]).unwrap();
1550        assert!(before.is_empty());
1551        assert_eq!(inferred.body.len(), 8);
1552    }
1553
1554    // Verify that values written to a `Ref` are properly shared between the
1555    // typed and untyped representations, that reads via `deref` and `read`
1556    // behave the same, and that writes via `deref_mut` and `write` behave the
1557    // same.
1558    fn test_new_helper(mut r: Ref<&mut [u8], AU64>) {
1559        // assert that the value starts at 0
1560        assert_eq!(*r, AU64(0));
1561        assert_eq!(Ref::read(&r), AU64(0));
1562
1563        // Assert that values written to the typed value are reflected in the
1564        // byte slice.
1565        const VAL1: AU64 = AU64(0xFF00FF00FF00FF00);
1566        *r = VAL1;
1567        assert_eq!(Ref::bytes(&r), &VAL1.to_bytes());
1568        *r = AU64(0);
1569        Ref::write(&mut r, VAL1);
1570        assert_eq!(Ref::bytes(&r), &VAL1.to_bytes());
1571
1572        // Assert that values written to the byte slice are reflected in the
1573        // typed value.
1574        const VAL2: AU64 = AU64(!VAL1.0); // different from `VAL1`
1575        Ref::bytes_mut(&mut r).copy_from_slice(&VAL2.to_bytes()[..]);
1576        assert_eq!(*r, VAL2);
1577        assert_eq!(Ref::read(&r), VAL2);
1578    }
1579
1580    // Verify that values written to a `Ref` are properly shared between the
1581    // typed and untyped representations; pass a value with `typed_len` `AU64`s
1582    // backed by an array of `typed_len * 8` bytes.
1583    fn test_new_helper_slice(mut r: Ref<&mut [u8], [AU64]>, typed_len: usize) {
1584        // Assert that the value starts out zeroed.
1585        assert_eq!(&*r, vec![AU64(0); typed_len].as_slice());
1586
1587        // Check the backing storage is the exact same slice.
1588        let untyped_len = typed_len * 8;
1589        assert_eq!(Ref::bytes(&r).len(), untyped_len);
1590        assert_eq!(Ref::bytes(&r).as_ptr(), r.as_ptr().cast::<u8>());
1591
1592        // Assert that values written to the typed value are reflected in the
1593        // byte slice.
1594        const VAL1: AU64 = AU64(0xFF00FF00FF00FF00);
1595        for typed in &mut *r {
1596            *typed = VAL1;
1597        }
1598        assert_eq!(Ref::bytes(&r), VAL1.0.to_ne_bytes().repeat(typed_len).as_slice());
1599
1600        // Assert that values written to the byte slice are reflected in the
1601        // typed value.
1602        const VAL2: AU64 = AU64(!VAL1.0); // different from VAL1
1603        Ref::bytes_mut(&mut r).copy_from_slice(&VAL2.0.to_ne_bytes().repeat(typed_len));
1604        assert!(r.iter().copied().all(|x| x == VAL2));
1605    }
1606
1607    #[test]
1608    fn test_new_aligned_sized() {
1609        // Test that a properly-aligned, properly-sized buffer works for new,
1610        // new_from_prefix, and new_from_suffix, and that new_from_prefix and
1611        // new_from_suffix return empty slices. Test that a properly-aligned
1612        // buffer whose length is a multiple of the element size works for
1613        // new_slice.
1614
1615        // A buffer with an alignment of 8.
1616        let mut buf = Align::<[u8; 8], AU64>::default();
1617        // `buf.t` should be aligned to 8, so this should always succeed.
1618        test_new_helper(Ref::<_, AU64>::from_bytes(&mut buf.t[..]).unwrap());
1619        {
1620            // In a block so that `r` and `suffix` don't live too long.
1621            buf.set_default();
1622            let (r, suffix) = Ref::<_, AU64>::from_prefix(&mut buf.t[..]).unwrap();
1623            assert!(suffix.is_empty());
1624            test_new_helper(r);
1625        }
1626        {
1627            buf.set_default();
1628            let (prefix, r) = Ref::<_, AU64>::from_suffix(&mut buf.t[..]).unwrap();
1629            assert!(prefix.is_empty());
1630            test_new_helper(r);
1631        }
1632
1633        // A buffer with alignment 8 and length 24. We choose this length very
1634        // intentionally: if we instead used length 16, then the prefix and
1635        // suffix lengths would be identical. In the past, we used length 16,
1636        // which resulted in this test failing to discover the bug uncovered in
1637        // #506.
1638        let mut buf = Align::<[u8; 24], AU64>::default();
1639        // `buf.t` should be aligned to 8 and have a length which is a multiple
1640        // of `size_of::<AU64>()`, so this should always succeed.
1641        test_new_helper_slice(Ref::<_, [AU64]>::from_bytes(&mut buf.t[..]).unwrap(), 3);
1642        buf.set_default();
1643        let r = Ref::<_, [AU64]>::from_bytes_with_elems(&mut buf.t[..], 3).unwrap();
1644        test_new_helper_slice(r, 3);
1645
1646        let ascending: [u8; 24] = (0..24).collect::<Vec<_>>().try_into().unwrap();
1647        // 16 ascending bytes followed by 8 zeros.
1648        let mut ascending_prefix = ascending;
1649        ascending_prefix[16..].copy_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0]);
1650        // 8 zeros followed by 16 ascending bytes.
1651        let mut ascending_suffix = ascending;
1652        ascending_suffix[..8].copy_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0]);
1653        {
1654            buf.t = ascending_suffix;
1655            let (r, suffix) = Ref::<_, [AU64]>::from_prefix_with_elems(&mut buf.t[..], 1).unwrap();
1656            assert_eq!(suffix, &ascending[8..]);
1657            test_new_helper_slice(r, 1);
1658        }
1659        {
1660            buf.t = ascending_prefix;
1661            let (prefix, r) = Ref::<_, [AU64]>::from_suffix_with_elems(&mut buf.t[..], 1).unwrap();
1662            assert_eq!(prefix, &ascending[..16]);
1663            test_new_helper_slice(r, 1);
1664        }
1665    }
1666
1667    #[test]
1668    fn test_new_oversized() {
1669        // Test that a properly-aligned, overly-sized buffer works for
1670        // `new_from_prefix` and `new_from_suffix`, and that they return the
1671        // remainder and prefix of the slice respectively.
1672
1673        let mut buf = Align::<[u8; 16], AU64>::default();
1674        {
1675            // In a block so that `r` and `suffix` don't live too long. `buf.t`
1676            // should be aligned to 8, so this should always succeed.
1677            let (r, suffix) = Ref::<_, AU64>::from_prefix(&mut buf.t[..]).unwrap();
1678            assert_eq!(suffix.len(), 8);
1679            test_new_helper(r);
1680        }
1681        {
1682            buf.set_default();
1683            // `buf.t` should be aligned to 8, so this should always succeed.
1684            let (prefix, r) = Ref::<_, AU64>::from_suffix(&mut buf.t[..]).unwrap();
1685            assert_eq!(prefix.len(), 8);
1686            test_new_helper(r);
1687        }
1688    }
1689
1690    #[test]
1691    #[allow(clippy::cognitive_complexity)]
1692    fn test_new_error() {
1693        // Fail because the buffer is too large.
1694
1695        // A buffer with an alignment of 8.
1696        let buf = Align::<[u8; 16], AU64>::default();
1697        // `buf.t` should be aligned to 8, so only the length check should fail.
1698        assert!(Ref::<_, AU64>::from_bytes(&buf.t[..]).is_err());
1699
1700        // Fail because the buffer is too small.
1701
1702        // A buffer with an alignment of 8.
1703        let buf = Align::<[u8; 4], AU64>::default();
1704        // `buf.t` should be aligned to 8, so only the length check should fail.
1705        assert!(Ref::<_, AU64>::from_bytes(&buf.t[..]).is_err());
1706        assert!(Ref::<_, AU64>::from_prefix(&buf.t[..]).is_err());
1707        assert!(Ref::<_, AU64>::from_suffix(&buf.t[..]).is_err());
1708
1709        // Fail because the length is not a multiple of the element size.
1710
1711        let buf = Align::<[u8; 12], AU64>::default();
1712        // `buf.t` has length 12, but element size is 8.
1713        assert!(Ref::<_, [AU64]>::from_bytes(&buf.t[..]).is_err());
1714
1715        // Fail because the buffer is too short.
1716        let buf = Align::<[u8; 12], AU64>::default();
1717        // `buf.t` has length 12, but the element size is 8 (and we're expecting
1718        // two of them). For each function, we test with a length that would
1719        // cause the size to overflow `usize`, and with a normal length that
1720        // will fail thanks to the buffer being too short; these are different
1721        // error paths, and while the error types are the same, the distinction
1722        // shows up in code coverage metrics.
1723        let n = (usize::MAX / mem::size_of::<AU64>()) + 1;
1724        assert!(Ref::<_, [AU64]>::from_bytes_with_elems(&buf.t[..], n).is_err());
1725        assert!(Ref::<_, [AU64]>::from_bytes_with_elems(&buf.t[..], 2).is_err());
1726        assert!(Ref::<_, [AU64]>::from_prefix_with_elems(&buf.t[..], n).is_err());
1727        assert!(Ref::<_, [AU64]>::from_prefix_with_elems(&buf.t[..], 2).is_err());
1728        assert!(Ref::<_, [AU64]>::from_suffix_with_elems(&buf.t[..], n).is_err());
1729        assert!(Ref::<_, [AU64]>::from_suffix_with_elems(&buf.t[..], 2).is_err());
1730
1731        // Fail because the alignment is insufficient.
1732
1733        // A buffer with an alignment of 8. An odd buffer size is chosen so that
1734        // the last byte of the buffer has odd alignment.
1735        let buf = Align::<[u8; 13], AU64>::default();
1736        // Slicing from 1, we get a buffer with size 12 (so the length check
1737        // should succeed) but an alignment of only 1, which is insufficient.
1738        assert!(Ref::<_, AU64>::from_bytes(&buf.t[1..]).is_err());
1739        assert!(Ref::<_, AU64>::from_prefix(&buf.t[1..]).is_err());
1740        assert!(Ref::<_, [AU64]>::from_bytes(&buf.t[1..]).is_err());
1741        assert!(Ref::<_, [AU64]>::from_bytes_with_elems(&buf.t[1..], 1).is_err());
1742        assert!(Ref::<_, [AU64]>::from_prefix_with_elems(&buf.t[1..], 1).is_err());
1743        assert!(Ref::<_, [AU64]>::from_suffix_with_elems(&buf.t[1..], 1).is_err());
1744        // Slicing is unnecessary here because `new_from_suffix` uses the suffix
1745        // of the slice, which has odd alignment.
1746        assert!(Ref::<_, AU64>::from_suffix(&buf.t[..]).is_err());
1747
1748        // Fail due to arithmetic overflow.
1749
1750        let buf = Align::<[u8; 16], AU64>::default();
1751        let unreasonable_len = usize::MAX / mem::size_of::<AU64>() + 1;
1752        assert!(Ref::<_, [AU64]>::from_prefix_with_elems(&buf.t[..], unreasonable_len).is_err());
1753        assert!(Ref::<_, [AU64]>::from_suffix_with_elems(&buf.t[..], unreasonable_len).is_err());
1754    }
1755
1756    #[test]
1757    #[allow(unstable_name_collisions)]
1758    #[allow(clippy::as_conversions)]
1759    fn test_into_ref_mut() {
1760        #[allow(unused)]
1761        use crate::util::AsAddress as _;
1762
1763        let mut buf = Align::<[u8; 8], u64>::default();
1764        let r = Ref::<_, u64>::from_bytes(&buf.t[..]).unwrap();
1765        let rf = Ref::into_ref(r);
1766        assert_eq!(rf, &0u64);
1767        let buf_addr = (&buf.t as *const [u8; 8]).addr();
1768        assert_eq!((rf as *const u64).addr(), buf_addr);
1769
1770        let r = Ref::<_, u64>::from_bytes(&mut buf.t[..]).unwrap();
1771        let rf = Ref::into_mut(r);
1772        assert_eq!(rf, &mut 0u64);
1773        assert_eq!((rf as *mut u64).addr(), buf_addr);
1774
1775        *rf = u64::MAX;
1776        assert_eq!(buf.t, [0xFF; 8]);
1777
1778        // Exercise the unsized `into_mut` route, which must use the metadata
1779        // retained by the constructor rather than infer fresh metadata.
1780        let mut buf = Align::<[u8; 8], u16>::default();
1781        let r = Ref::<_, [u16]>::from_bytes_with_elems(&mut buf.t[..], 4).unwrap();
1782        let rf = Ref::into_mut(r);
1783        assert_eq!(rf.len(), 4);
1784    }
1785
1786    #[test]
1787    fn test_display_debug() {
1788        let buf = Align::<[u8; 8], u64>::default();
1789        let r = Ref::<_, u64>::from_bytes(&buf.t[..]).unwrap();
1790        assert_eq!(format!("{}", r), "0");
1791        assert_eq!(format!("{:?}", r), "Ref(0)");
1792
1793        let buf = Align::<[u8; 8], u64>::default();
1794        let r = Ref::<_, [u64]>::from_bytes(&buf.t[..]).unwrap();
1795        assert_eq!(format!("{:?}", r), "Ref([0])");
1796    }
1797
1798    #[test]
1799    fn test_eq() {
1800        let buf1 = 0_u64;
1801        let r1 = Ref::<_, u64>::from_bytes(buf1.as_bytes()).unwrap();
1802        let buf2 = 0_u64;
1803        let r2 = Ref::<_, u64>::from_bytes(buf2.as_bytes()).unwrap();
1804        assert_eq!(r1, r2);
1805    }
1806
1807    #[test]
1808    fn test_ne() {
1809        let buf1 = 0_u64;
1810        let r1 = Ref::<_, u64>::from_bytes(buf1.as_bytes()).unwrap();
1811        let buf2 = 1_u64;
1812        let r2 = Ref::<_, u64>::from_bytes(buf2.as_bytes()).unwrap();
1813        assert_ne!(r1, r2);
1814    }
1815
1816    #[test]
1817    fn test_ord() {
1818        let buf1 = 0_u64;
1819        let r1 = Ref::<_, u64>::from_bytes(buf1.as_bytes()).unwrap();
1820        let buf2 = 1_u64;
1821        let r2 = Ref::<_, u64>::from_bytes(buf2.as_bytes()).unwrap();
1822        assert!(r1 < r2);
1823        assert_eq!(PartialOrd::partial_cmp(&r1, &r2), Some(Ordering::Less));
1824        assert_eq!(Ord::cmp(&r1, &r2), Ordering::Less);
1825    }
1826}
1827
1828#[cfg(all(test, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS))]
1829mod benches {
1830    use test::{self, Bencher};
1831
1832    use super::*;
1833    use crate::util::testutil::*;
1834
1835    #[bench]
1836    fn bench_from_bytes_sized(b: &mut Bencher) {
1837        let buf = Align::<[u8; 8], AU64>::default();
1838        // `buf.t` should be aligned to 8, so this should always succeed.
1839        let bytes = &buf.t[..];
1840        b.iter(|| test::black_box(Ref::<_, AU64>::from_bytes(test::black_box(bytes)).unwrap()));
1841    }
1842
1843    #[bench]
1844    fn bench_into_ref_sized(b: &mut Bencher) {
1845        let buf = Align::<[u8; 8], AU64>::default();
1846        let bytes = &buf.t[..];
1847        let r = Ref::<_, AU64>::from_bytes(bytes).unwrap();
1848        b.iter(|| test::black_box(Ref::into_ref(test::black_box(r))));
1849    }
1850
1851    #[bench]
1852    fn bench_into_mut_sized(b: &mut Bencher) {
1853        let mut buf = Align::<[u8; 8], AU64>::default();
1854        let buf = &mut buf.t[..];
1855        let _ = Ref::<_, AU64>::from_bytes(&mut *buf).unwrap();
1856        b.iter(move || {
1857            // SAFETY: The preceding `from_bytes` succeeded, and so we know that
1858            // `buf` is validly aligned and has the `size_of::<AU64>()` byte
1859            // length required by `new_sized_unchecked` [1].
1860            //
1861            // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of.html:
1862            //
1863            //     Returns the size of a type in bytes.
1864            let r = unsafe { Ref::<&mut [u8], AU64>::new_sized_unchecked(&mut *buf) };
1865            test::black_box(Ref::into_mut(test::black_box(r)));
1866        });
1867    }
1868
1869    #[bench]
1870    fn bench_deref_sized(b: &mut Bencher) {
1871        let buf = Align::<[u8; 8], AU64>::default();
1872        let bytes = &buf.t[..];
1873        let r = Ref::<_, AU64>::from_bytes(bytes).unwrap();
1874        b.iter(|| {
1875            let temp = test::black_box(r);
1876            test::black_box(temp.deref());
1877        });
1878    }
1879
1880    #[bench]
1881    fn bench_deref_mut_sized(b: &mut Bencher) {
1882        let mut buf = Align::<[u8; 8], AU64>::default();
1883        let buf = &mut buf.t[..];
1884        let _ = Ref::<_, AU64>::from_bytes(&mut *buf).unwrap();
1885        b.iter(|| {
1886            // SAFETY: The preceding `from_bytes` succeeded, and so we know that
1887            // `buf` is validly aligned and has the `size_of::<AU64>()` byte
1888            // length required by `new_sized_unchecked` [1].
1889            //
1890            // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of.html:
1891            //
1892            //     Returns the size of a type in bytes.
1893            let r = unsafe { Ref::<&mut [u8], AU64>::new_sized_unchecked(&mut *buf) };
1894            let mut temp = test::black_box(r);
1895            test::black_box(temp.deref_mut());
1896        });
1897    }
1898}