xref: /linux/rust/zerocopy/src/ref.rs (revision 056a5087d87ead77dedbe9cf5bde53b7cd4b4651)
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.
11 use super::*;
12 use crate::pointer::{
13     BecauseInvariantsEq, BecauseMutationCompatible, MutationCompatible, TransmuteFromPtr,
14 };
15 
16 mod 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.
198 pub use def::Ref;
199 
200 use crate::pointer::{
201     invariant::{Aligned, BecauseExclusive, Initialized, Unaligned, Valid},
202     BecauseRead, PtrInner,
203 };
204 
205 impl<B, T> Ref<B, T>
206 where
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 
223 impl<B, T> Ref<B, T>
224 where
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 
271 impl<B, T> Ref<B, T>
272 where
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 
323 impl<B, T> Ref<B, T>
324 where
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 
453 impl<B, T> Ref<B, T>
454 where
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 
504 impl<B, T> Ref<B, T>
505 where
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 
609 impl<'a, B, T> Ref<B, T>
610 where
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 
657 impl<'a, B, T> Ref<B, T>
658 where
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 
712 impl<B, T> Ref<B, T>
713 where
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 
730 impl<B, T> Ref<B, T>
731 where
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 
748 impl<B, T> Ref<B, T>
749 where
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 
773 impl<B, T> Ref<B, T>
774 where
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 
798 impl<B, T> Deref for Ref<B, T>
799 where
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 
838 impl<B, T> DerefMut for Ref<B, T>
839 where
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 
888 impl<T, B> Display for Ref<B, T>
889 where
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 
900 impl<T, B> Debug for Ref<B, T>
901 where
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 
912 impl<T, B> Eq for Ref<B, T>
913 where
914     B: ByteSlice,
915     T: FromBytes + Eq + KnownLayout + Immutable + ?Sized,
916 {
917 }
918 
919 impl<T, B> PartialEq for Ref<B, T>
920 where
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 
930 impl<T, B> Ord for Ref<B, T>
931 where
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 
943 impl<T, B> PartialOrd for Ref<B, T>
944 where
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)]
960 unsafe fn cast_for_sized<'a, T, A, R, S>(
961     ptr: Ptr<'a, [u8], (A, Aligned, Valid)>,
962 ) -> Ptr<'a, T, (A, Unaligned, Valid)>
963 where
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)]
998 mod 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))]
1299 mod 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 }
1359