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