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