zerocopy/util/
mod.rs

1// Copyright 2023 The Fuchsia Authors
2//
3// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
4// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
5// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
6// This file may not be copied, modified, or distributed except according to
7// those terms.
8
9#[macro_use]
10pub(crate) mod macros;
11
12#[doc(hidden)]
13pub mod macro_util;
14
15use core::{
16    marker::PhantomData,
17    mem::{self, ManuallyDrop},
18    num::NonZeroUsize,
19    ptr::NonNull,
20};
21
22use super::*;
23
24/// Like [`PhantomData`], but [`Send`] and [`Sync`] regardless of whether the
25/// wrapped `T` is.
26pub(crate) struct SendSyncPhantomData<T: ?Sized>(PhantomData<T>);
27
28// SAFETY: `SendSyncPhantomData` does not enable any behavior which isn't sound
29// to be called from multiple threads.
30unsafe impl<T: ?Sized> Send for SendSyncPhantomData<T> {}
31// SAFETY: `SendSyncPhantomData` does not enable any behavior which isn't sound
32// to be called from multiple threads.
33unsafe impl<T: ?Sized> Sync for SendSyncPhantomData<T> {}
34
35impl<T: ?Sized> Default for SendSyncPhantomData<T> {
36    fn default() -> SendSyncPhantomData<T> {
37        SendSyncPhantomData(PhantomData)
38    }
39}
40
41impl<T: ?Sized> PartialEq for SendSyncPhantomData<T> {
42    fn eq(&self, other: &Self) -> bool {
43        self.0.eq(&other.0)
44    }
45}
46
47impl<T: ?Sized> Eq for SendSyncPhantomData<T> {}
48
49pub(crate) trait AsAddress {
50    fn addr(self) -> usize;
51}
52
53impl<T: ?Sized> AsAddress for &T {
54    #[inline(always)]
55    fn addr(self) -> usize {
56        let ptr: *const T = self;
57        AsAddress::addr(ptr)
58    }
59}
60
61impl<T: ?Sized> AsAddress for &mut T {
62    #[inline(always)]
63    fn addr(self) -> usize {
64        let ptr: *const T = self;
65        AsAddress::addr(ptr)
66    }
67}
68
69impl<T: ?Sized> AsAddress for NonNull<T> {
70    #[inline(always)]
71    fn addr(self) -> usize {
72        AsAddress::addr(self.as_ptr())
73    }
74}
75
76impl<T: ?Sized> AsAddress for *const T {
77    #[inline(always)]
78    fn addr(self) -> usize {
79        // FIXME(#181), FIXME(https://github.com/rust-lang/rust/issues/95228):
80        // Use `.addr()` instead of `as usize` once it's stable, and get rid of
81        // this `allow`. Currently, `as usize` is the only way to accomplish
82        // this.
83        #[allow(clippy::as_conversions)]
84        #[cfg_attr(
85            __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS,
86            allow(lossy_provenance_casts)
87        )]
88        return self.cast::<()>() as usize;
89    }
90}
91
92impl<T: ?Sized> AsAddress for *mut T {
93    #[inline(always)]
94    fn addr(self) -> usize {
95        let ptr: *const T = self;
96        AsAddress::addr(ptr)
97    }
98}
99
100/// Validates that `t` is aligned to `align_of::<U>()`.
101#[inline(always)]
102pub(crate) fn validate_aligned_to<T: AsAddress, U>(t: T) -> Result<(), AlignmentError<(), U>> {
103    // `mem::align_of::<U>()` is guaranteed to return a non-zero value, which in
104    // turn guarantees that this mod operation will not panic.
105    #[allow(clippy::arithmetic_side_effects)]
106    let remainder = t.addr() % mem::align_of::<U>();
107    if remainder == 0 {
108        Ok(())
109    } else {
110        // SAFETY: We just confirmed that `t.addr() % align_of::<U>() != 0`.
111        // That's only possible if `align_of::<U>() > 1`.
112        Err(unsafe { AlignmentError::new_unchecked(()) })
113    }
114}
115
116/// Returns the bytes needed to pad `len` to the next multiple of `align`.
117///
118/// This function assumes that align is a power of two; there are no guarantees
119/// on the answer it gives if this is not the case.
120#[cfg_attr(
121    kani,
122    kani::requires(len <= isize::MAX as usize),
123    kani::requires(align.is_power_of_two()),
124    kani::ensures(|&p| (len + p) % align.get() == 0),
125    // Ensures that we add the minimum required padding.
126    kani::ensures(|&p| p < align.get()),
127)]
128pub(crate) const fn padding_needed_for(len: usize, align: NonZeroUsize) -> usize {
129    #[cfg(kani)]
130    #[kani::proof_for_contract(padding_needed_for)]
131    fn proof() {
132        padding_needed_for(kani::any(), kani::any());
133    }
134
135    // Abstractly, we want to compute:
136    //   align - (len % align).
137    // Handling the case where len%align is 0.
138    // Because align is a power of two, len % align = len & (align-1).
139    // Guaranteed not to underflow as align is nonzero.
140    #[allow(clippy::arithmetic_side_effects)]
141    let mask = align.get() - 1;
142
143    // To efficiently subtract this value from align, we can use the bitwise complement.
144    // Note that ((!len) & (align-1)) gives us a number that with (len &
145    // (align-1)) sums to align-1. So subtracting 1 from x before taking the
146    // complement subtracts `len` from `align`. Some quick inspection of
147    // cases shows that this also handles the case where `len % align = 0`
148    // correctly too: len-1 % align then equals align-1, so the complement mod
149    // align will be 0, as desired.
150    //
151    // The following reasoning can be verified quickly by an SMT solver
152    // supporting the theory of bitvectors:
153    // ```smtlib
154    // ; Naive implementation of padding
155    // (define-fun padding1 (
156    //     (len (_ BitVec 32))
157    //     (align (_ BitVec 32))) (_ BitVec 32)
158    //    (ite
159    //      (= (_ bv0 32) (bvand len (bvsub align (_ bv1 32))))
160    //      (_ bv0 32)
161    //      (bvsub align (bvand len (bvsub align (_ bv1 32))))))
162    //
163    // ; The implementation below
164    // (define-fun padding2 (
165    //     (len (_ BitVec 32))
166    //     (align (_ BitVec 32))) (_ BitVec 32)
167    // (bvand (bvnot (bvsub len (_ bv1 32))) (bvsub align (_ bv1 32))))
168    //
169    // (define-fun is-power-of-two ((x (_ BitVec 32))) Bool
170    //   (= (_ bv0 32) (bvand x (bvsub x (_ bv1 32)))))
171    //
172    // (declare-const len (_ BitVec 32))
173    // (declare-const align (_ BitVec 32))
174    // ; Search for a case where align is a power of two and padding2 disagrees with padding1
175    // (assert (and (is-power-of-two align)
176    //              (not (= (padding1 len align) (padding2 len align)))))
177    // (simplify (padding1 (_ bv300 32) (_ bv32 32))) ; 20
178    // (simplify (padding2 (_ bv300 32) (_ bv32 32))) ; 20
179    // (simplify (padding1 (_ bv322 32) (_ bv32 32))) ; 30
180    // (simplify (padding2 (_ bv322 32) (_ bv32 32))) ; 30
181    // (simplify (padding1 (_ bv8 32) (_ bv8 32)))    ; 0
182    // (simplify (padding2 (_ bv8 32) (_ bv8 32)))    ; 0
183    // (check-sat) ; unsat, also works for 64-bit bitvectors
184    // ```
185    !(len.wrapping_sub(1)) & mask
186}
187
188/// Rounds `n` down to the largest value `m` such that `m <= n` and `m % align
189/// == 0`.
190///
191/// # Panics
192///
193/// May panic if `align` is not a power of two. Even if it doesn't panic in this
194/// case, it will produce nonsense results.
195#[inline(always)]
196#[cfg_attr(
197    kani,
198    kani::requires(align.is_power_of_two()),
199    kani::ensures(|&m| m <= n && m % align.get() == 0),
200    // Guarantees that `m` is the *largest* value such that `m % align == 0`.
201    kani::ensures(|&m| {
202        // If this `checked_add` fails, then the next multiple would wrap
203        // around, which trivially satisfies the "largest value" requirement.
204        m.checked_add(align.get()).map(|next_mul| next_mul > n).unwrap_or(true)
205    })
206)]
207pub(crate) const fn round_down_to_next_multiple_of_alignment(
208    n: usize,
209    align: NonZeroUsize,
210) -> usize {
211    #[cfg(kani)]
212    #[kani::proof_for_contract(round_down_to_next_multiple_of_alignment)]
213    fn proof() {
214        round_down_to_next_multiple_of_alignment(kani::any(), kani::any());
215    }
216
217    let align = align.get();
218    #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
219    debug_assert!(align.is_power_of_two());
220
221    // Subtraction can't underflow because `align.get() >= 1`.
222    #[allow(clippy::arithmetic_side_effects)]
223    let mask = !(align - 1);
224    n & mask
225}
226
227pub(crate) const fn max(a: NonZeroUsize, b: NonZeroUsize) -> NonZeroUsize {
228    if a.get() < b.get() {
229        b
230    } else {
231        a
232    }
233}
234
235pub(crate) const fn min(a: NonZeroUsize, b: NonZeroUsize) -> NonZeroUsize {
236    if a.get() > b.get() {
237        b
238    } else {
239        a
240    }
241}
242
243/// Copies `src` into the prefix of `dst`.
244///
245/// # Safety
246///
247/// The caller guarantees that `src.len() <= dst.len()`.
248#[inline(always)]
249pub(crate) unsafe fn copy_unchecked(src: &[u8], dst: &mut [u8]) {
250    debug_assert!(src.len() <= dst.len());
251    // SAFETY: This invocation satisfies the safety contract of
252    // copy_nonoverlapping [1]:
253    // - `src.as_ptr()` is trivially valid for reads of `src.len()` bytes
254    // - `dst.as_ptr()` is valid for writes of `src.len()` bytes, because the
255    //   caller has promised that `src.len() <= dst.len()`
256    // - `src` and `dst` are, trivially, properly aligned
257    // - the region of memory beginning at `src` with a size of `src.len()`
258    //   bytes does not overlap with the region of memory beginning at `dst`
259    //   with the same size, because `dst` is derived from an exclusive
260    //   reference.
261    unsafe {
262        core::ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), src.len());
263    };
264}
265
266/// Unsafely transmutes the given `src` into a type `Dst`.
267///
268/// # Safety
269///
270/// The value `src` must be a valid instance of `Dst`.
271#[inline(always)]
272pub(crate) const unsafe fn transmute_unchecked<Src, Dst>(src: Src) -> Dst {
273    static_assert!(Src, Dst => core::mem::size_of::<Src>() == core::mem::size_of::<Dst>());
274
275    #[repr(C)]
276    union Transmute<Src, Dst> {
277        src: ManuallyDrop<Src>,
278        dst: ManuallyDrop<Dst>,
279    }
280
281    // SAFETY: Since `Transmute<Src, Dst>` is `#[repr(C)]`, its `src` and `dst`
282    // fields both start at the same offset and the types of those fields are
283    // transparent wrappers around `Src` and `Dst` [1]. Consequently,
284    // initializng `Transmute` with with `src` and then reading out `dst` is
285    // equivalent to transmuting from `Src` to `Dst` [2]. Transmuting from `src`
286    // to `Dst` is valid because — by contract on the caller — `src` is a valid
287    // instance of `Dst`.
288    //
289    // [1] Per https://doc.rust-lang.org/1.82.0/std/mem/struct.ManuallyDrop.html:
290    //
291    //     `ManuallyDrop<T>` is guaranteed to have the same layout and bit
292    //     validity as `T`, and is subject to the same layout optimizations as
293    //     `T`.
294    //
295    // [2] Per https://doc.rust-lang.org/1.82.0/reference/items/unions.html#reading-and-writing-union-fields:
296    //
297    //     Effectively, writing to and then reading from a union with the C
298    //     representation is analogous to a transmute from the type used for
299    //     writing to the type used for reading.
300    unsafe { ManuallyDrop::into_inner(Transmute { src: ManuallyDrop::new(src) }.dst) }
301}
302
303/// Uses `allocate` to create a `Box<T>`.
304///
305/// # Errors
306///
307/// Returns an error on allocation failure. Allocation failure is guaranteed
308/// never to cause a panic or an abort.
309///
310/// # Safety
311///
312/// `allocate` must be either `alloc::alloc::alloc` or
313/// `alloc::alloc::alloc_zeroed`. The referent of the box returned by `new_box`
314/// has the same bit-validity as the referent of the pointer returned by the
315/// given `allocate` and sufficient size to store `T` with `meta`.
316#[must_use = "has no side effects (other than allocation)"]
317#[cfg(feature = "alloc")]
318#[inline]
319pub(crate) unsafe fn new_box<T>(
320    meta: T::PointerMetadata,
321    allocate: unsafe fn(core::alloc::Layout) -> *mut u8,
322) -> Result<alloc::boxed::Box<T>, AllocError>
323where
324    T: ?Sized + crate::KnownLayout,
325{
326    let size = match meta.size_for_metadata(T::LAYOUT) {
327        Some(size) => size,
328        None => return Err(AllocError),
329    };
330
331    let align = T::LAYOUT.align.get();
332    // On stable Rust versions <= 1.64.0, `Layout::from_size_align` has a bug in
333    // which sufficiently-large allocations (those which, when rounded up to the
334    // alignment, overflow `isize`) are not rejected, which can cause undefined
335    // behavior. See #64 for details.
336    //
337    // FIXME(#67): Once our MSRV is > 1.64.0, remove this assertion.
338    #[allow(clippy::as_conversions)]
339    let max_alloc = (isize::MAX as usize).saturating_sub(align);
340    if size > max_alloc {
341        return Err(AllocError);
342    }
343
344    // FIXME(https://github.com/rust-lang/rust/issues/55724): Use
345    // `Layout::repeat` once it's stabilized.
346    let layout = Layout::from_size_align(size, align).or(Err(AllocError))?;
347
348    let ptr = if layout.size() != 0 {
349        // SAFETY: By contract on the caller, `allocate` is either
350        // `alloc::alloc::alloc` or `alloc::alloc::alloc_zeroed`. The above
351        // check ensures their shared safety precondition: that the supplied
352        // layout is not zero-sized type [1].
353        //
354        // [1] Per https://doc.rust-lang.org/stable/std/alloc/trait.GlobalAlloc.html#tymethod.alloc:
355        //
356        //     This function is unsafe because undefined behavior can result if
357        //     the caller does not ensure that layout has non-zero size.
358        let ptr = unsafe { allocate(layout) };
359        match NonNull::new(ptr) {
360            Some(ptr) => ptr,
361            None => return Err(AllocError),
362        }
363    } else {
364        let align = T::LAYOUT.align.get();
365        // We use `transmute` instead of an `as` cast since Miri (with strict
366        // provenance enabled) notices and complains that an `as` cast creates a
367        // pointer with no provenance. Miri isn't smart enough to realize that
368        // we're only executing this branch when we're constructing a zero-sized
369        // `Box`, which doesn't require provenance.
370        //
371        // SAFETY: any initialized bit sequence is a bit-valid `*mut u8`. All
372        // bits of a `usize` are initialized.
373        #[allow(clippy::useless_transmute)]
374        let dangling = unsafe { mem::transmute::<usize, *mut u8>(align) };
375        // SAFETY: `dangling` is constructed from `T::LAYOUT.align`, which is a
376        // `NonZeroUsize`, which is guaranteed to be non-zero.
377        //
378        // `Box<[T]>` does not allocate when `T` is zero-sized or when `len` is
379        // zero, but it does require a non-null dangling pointer for its
380        // allocation.
381        //
382        // FIXME(https://github.com/rust-lang/rust/issues/95228): Use
383        // `std::ptr::without_provenance` once it's stable. That may optimize
384        // better. As written, Rust may assume that this consumes "exposed"
385        // provenance, and thus Rust may have to assume that this may consume
386        // provenance from any pointer whose provenance has been exposed.
387        unsafe { NonNull::new_unchecked(dangling) }
388    };
389
390    let ptr = T::raw_from_ptr_len(ptr, meta);
391
392    // FIXME(#429): Add a "SAFETY" comment and remove this `allow`. Make sure to
393    // include a justification that `ptr.as_ptr()` is validly-aligned in the ZST
394    // case (in which we manually construct a dangling pointer) and to justify
395    // why `Box` is safe to drop (it's because `allocate` uses the system
396    // allocator).
397    #[allow(clippy::undocumented_unsafe_blocks)]
398    Ok(unsafe { alloc::boxed::Box::from_raw(ptr.as_ptr()) })
399}
400
401mod len_of {
402    use super::*;
403
404    /// A witness type for metadata of a valid instance of `&T`.
405    pub(crate) struct MetadataOf<T: ?Sized + KnownLayout> {
406        /// # Safety
407        ///
408        /// The size of an instance of `&T` with the given metadata is not
409        /// larger than `isize::MAX`.
410        meta: T::PointerMetadata,
411        _p: PhantomData<T>,
412    }
413
414    impl<T: ?Sized + KnownLayout> Copy for MetadataOf<T> {}
415    impl<T: ?Sized + KnownLayout> Clone for MetadataOf<T> {
416        fn clone(&self) -> Self {
417            *self
418        }
419    }
420
421    impl<T: ?Sized> MetadataOf<T>
422    where
423        T: KnownLayout,
424    {
425        /// Returns `None` if `meta` is greater than `t`'s metadata.
426        #[inline(always)]
427        pub(crate) fn new_in_bounds(t: &T, meta: usize) -> Option<Self>
428        where
429            T: KnownLayout<PointerMetadata = usize>,
430        {
431            if meta <= Ptr::from_ref(t).len() {
432                // SAFETY: We have checked that `meta` is not greater than `t`'s
433                // metadata, which, by invariant on `&T`, addresses no more than
434                // `isize::MAX` bytes [1][2].
435                //
436                // [1] Per https://doc.rust-lang.org/1.85.0/std/primitive.reference.html#safety:
437                //
438                //    For all types, `T: ?Sized`, and for all `t: &T` or `t:
439                //    &mut T`, when such values cross an API boundary, the
440                //    following invariants must generally be upheld:
441                //
442                //    * `t` is non-null
443                //    * `t` is aligned to `align_of_val(t)`
444                //    * if `size_of_val(t) > 0`, then `t` is dereferenceable for
445                //      `size_of_val(t)` many bytes
446                //
447                //    If `t` points at address `a`, being "dereferenceable" for
448                //    N bytes means that the memory range `[a, a + N)` is all
449                //    contained within a single allocated object.
450                //
451                // [2] Per https://doc.rust-lang.org/1.85.0/std/ptr/index.html#allocated-object:
452                //
453                //    For any allocated object with `base` address, `size`, and
454                //    a set of `addresses`, the following are guaranteed:
455                //    - For all addresses `a` in `addresses`, `a` is in the
456                //      range `base .. (base + size)` (note that this requires
457                //      `a < base + size`, not `a <= base + size`)
458                //    - `base` is not equal to [`null()`] (i.e., the address
459                //      with the numerical value 0)
460                //    - `base + size <= usize::MAX`
461                //    - `size <= isize::MAX`
462                Some(unsafe { Self::new_unchecked(meta) })
463            } else {
464                None
465            }
466        }
467
468        /// # Safety
469        ///
470        /// The size of an instance of `&T` with the given metadata is not
471        /// larger than `isize::MAX`.
472        pub(crate) unsafe fn new_unchecked(meta: T::PointerMetadata) -> Self {
473            // SAFETY: The caller has promised that the size of an instance of
474            // `&T` with the given metadata is not larger than `isize::MAX`.
475            Self { meta, _p: PhantomData }
476        }
477
478        pub(crate) fn get(&self) -> T::PointerMetadata
479        where
480            T::PointerMetadata: Copy,
481        {
482            self.meta
483        }
484
485        #[inline]
486        pub(crate) fn padding_needed_for(&self) -> usize
487        where
488            T: KnownLayout<PointerMetadata = usize>,
489        {
490            let trailing_slice_layout = crate::trailing_slice_layout::<T>();
491            // SAFETY: By invariant on `self`, a `&T` with metadata `self.meta`
492            // describes an object of size `<= isize::MAX`. This computes the
493            // size of such a `&T` without any trailing padding, and so neither
494            // the multiplication nor the addition will overflow.
495            //
496            // FIXME(#67): Remove this allow. See NumExt for more details.
497            #[allow(unstable_name_collisions, clippy::incompatible_msrv)]
498            let unpadded_size = unsafe {
499                let trailing_size = self.meta.unchecked_mul(trailing_slice_layout.elem_size);
500                trailing_size.unchecked_add(trailing_slice_layout.offset)
501            };
502
503            util::padding_needed_for(unpadded_size, T::LAYOUT.align)
504        }
505
506        #[inline(always)]
507        pub(crate) fn validate_cast_and_convert_metadata(
508            addr: usize,
509            bytes_len: MetadataOf<[u8]>,
510            cast_type: CastType,
511            meta: Option<T::PointerMetadata>,
512        ) -> Result<(MetadataOf<T>, MetadataOf<[u8]>), MetadataCastError> {
513            let layout = match meta {
514                None => T::LAYOUT,
515                // This can return `None` if the metadata describes an object
516                // which can't fit in an `isize`.
517                Some(meta) => {
518                    let size = match meta.size_for_metadata(T::LAYOUT) {
519                        Some(size) => size,
520                        None => return Err(MetadataCastError::Size),
521                    };
522                    DstLayout { align: T::LAYOUT.align, size_info: crate::SizeInfo::Sized { size } }
523                }
524            };
525            // Lemma 0: By contract on `validate_cast_and_convert_metadata`, if
526            // the result is `Ok(..)`, then a `&T` with `elems` trailing slice
527            // elements is no larger in size than `bytes_len.get()`.
528            let (elems, split_at) =
529                layout.validate_cast_and_convert_metadata(addr, bytes_len.get(), cast_type)?;
530            let elems = T::PointerMetadata::from_elem_count(elems);
531
532            // For a slice DST type, if `meta` is `Some(elems)`, then we
533            // synthesize `layout` to describe a sized type whose size is equal
534            // to the size of the instance that we are asked to cast. For sized
535            // types, `validate_cast_and_convert_metadata` returns `elems == 0`.
536            // Thus, in this case, we need to use the `elems` passed by the
537            // caller, not the one returned by
538            // `validate_cast_and_convert_metadata`.
539            //
540            // Lemma 1: A `&T` with `elems` trailing slice elements is no larger
541            // in size than `bytes_len.get()`. Proof:
542            // - If `meta` is `None`, then `elems` satisfies this condition by
543            //   Lemma 0.
544            // - If `meta` is `Some(meta)`, then `layout` describes an object
545            //   whose size is equal to the size of an `&T` with `meta`
546            //   metadata. By Lemma 0, that size is not larger than
547            //   `bytes_len.get()`.
548            //
549            // Lemma 2: A `&T` with `elems` trailing slice elements is no larger
550            // than `isize::MAX` bytes. Proof: By Lemma 1, a `&T` with metadata
551            // `elems` is not larger in size than `bytes_len.get()`. By
552            // invariant on `MetadataOf<[u8]>`, a `&[u8]` with metadata
553            // `bytes_len` is not larger than `isize::MAX`. Because
554            // `size_of::<u8>()` is `1`, a `&[u8]` with metadata `bytes_len` has
555            // size `bytes_len.get()` bytes. Therefore, a `&T` with metadata
556            // `elems` has size not larger than `isize::MAX`.
557            let elems = meta.unwrap_or(elems);
558
559            // SAFETY: See Lemma 2.
560            let elems = unsafe { MetadataOf::new_unchecked(elems) };
561
562            // SAFETY: Let `size` be the size of a `&T` with metadata `elems`.
563            // By post-condition on `validate_cast_and_convert_metadata`, one of
564            // the following conditions holds:
565            // - `split_at == size`, in which case, by Lemma 2, `split_at <=
566            //   isize::MAX`. Since `size_of::<u8>() == 1`, a `[u8]` with
567            //   `split_at` elems has size not larger than `isize::MAX`.
568            // - `split_at == bytes_len - size`. Since `bytes_len:
569            //   MetadataOf<u8>`, and since `size` is non-negative, `split_at`
570            //   addresses no more bytes than `bytes_len` does. Since
571            //   `bytes_len: MetadataOf<u8>`, `bytes_len` describes a `[u8]`
572            //   which has no more than `isize::MAX` bytes, and thus so does
573            //   `split_at`.
574            let split_at = unsafe { MetadataOf::<[u8]>::new_unchecked(split_at) };
575            Ok((elems, split_at))
576        }
577    }
578}
579
580pub(crate) use len_of::MetadataOf;
581
582/// Since we support multiple versions of Rust, there are often features which
583/// have been stabilized in the most recent stable release which do not yet
584/// exist (stably) on our MSRV. This module provides polyfills for those
585/// features so that we can write more "modern" code, and just remove the
586/// polyfill once our MSRV supports the corresponding feature. Without this,
587/// we'd have to write worse/more verbose code and leave FIXME comments sprinkled
588/// throughout the codebase to update to the new pattern once it's stabilized.
589///
590/// Each trait is imported as `_` at the crate root; each polyfill should "just
591/// work" at usage sites.
592pub(crate) mod polyfills {
593    use core::ptr::{self, NonNull};
594
595    // A polyfill for `NonNull::slice_from_raw_parts` that we can use before our
596    // MSRV is 1.70, when that function was stabilized.
597    //
598    // The `#[allow(unused)]` is necessary because, on sufficiently recent
599    // toolchain versions, `ptr.slice_from_raw_parts()` resolves to the inherent
600    // method rather than to this trait, and so this trait is considered unused.
601    //
602    // FIXME(#67): Once our MSRV is 1.70, remove this.
603    #[allow(unused)]
604    pub(crate) trait NonNullExt<T> {
605        fn slice_from_raw_parts(data: Self, len: usize) -> NonNull<[T]>;
606    }
607
608    impl<T> NonNullExt<T> for NonNull<T> {
609        // NOTE on coverage: this will never be tested in nightly since it's a
610        // polyfill for a feature which has been stabilized on our nightly
611        // toolchain.
612        #[cfg_attr(
613            all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS),
614            coverage(off)
615        )]
616        #[inline(always)]
617        fn slice_from_raw_parts(data: Self, len: usize) -> NonNull<[T]> {
618            let ptr = ptr::slice_from_raw_parts_mut(data.as_ptr(), len);
619            // SAFETY: `ptr` is converted from `data`, which is non-null.
620            unsafe { NonNull::new_unchecked(ptr) }
621        }
622    }
623
624    // A polyfill for `Self::unchecked_sub` that we can use until methods like
625    // `usize::unchecked_sub` is stabilized.
626    //
627    // The `#[allow(unused)]` is necessary because, on sufficiently recent
628    // toolchain versions, `ptr.slice_from_raw_parts()` resolves to the inherent
629    // method rather than to this trait, and so this trait is considered unused.
630    //
631    // FIXME(#67): Once our MSRV is high enough, remove this.
632    #[allow(unused)]
633    pub(crate) trait NumExt {
634        /// Subtract without checking for underflow.
635        ///
636        /// # Safety
637        ///
638        /// The caller promises that the subtraction will not underflow.
639        unsafe fn unchecked_sub(self, rhs: Self) -> Self;
640
641        /// Add without checking for overflow.
642        ///
643        /// # Safety
644        ///
645        /// The caller promises that the addition will not overflow.
646        unsafe fn unchecked_add(self, rhs: Self) -> Self;
647
648        /// Multiply without checking for overflow.
649        ///
650        /// # Safety
651        ///
652        /// The caller promises that the multiplication will not overflow.
653        unsafe fn unchecked_mul(self, rhs: Self) -> Self;
654    }
655
656    impl NumExt for usize {
657        // NOTE on coverage: this will never be tested in nightly since it's a
658        // polyfill for a feature which has been stabilized on our nightly
659        // toolchain.
660        #[cfg_attr(
661            all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS),
662            coverage(off)
663        )]
664        #[inline(always)]
665        unsafe fn unchecked_sub(self, rhs: usize) -> usize {
666            match self.checked_sub(rhs) {
667                Some(x) => x,
668                None => {
669                    // SAFETY: The caller promises that the subtraction will not
670                    // underflow.
671                    unsafe { core::hint::unreachable_unchecked() }
672                }
673            }
674        }
675
676        // NOTE on coverage: this will never be tested in nightly since it's a
677        // polyfill for a feature which has been stabilized on our nightly
678        // toolchain.
679        #[cfg_attr(
680            all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS),
681            coverage(off)
682        )]
683        #[inline(always)]
684        unsafe fn unchecked_add(self, rhs: usize) -> usize {
685            match self.checked_add(rhs) {
686                Some(x) => x,
687                None => {
688                    // SAFETY: The caller promises that the addition will not
689                    // overflow.
690                    unsafe { core::hint::unreachable_unchecked() }
691                }
692            }
693        }
694
695        // NOTE on coverage: this will never be tested in nightly since it's a
696        // polyfill for a feature which has been stabilized on our nightly
697        // toolchain.
698        #[cfg_attr(
699            all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS),
700            coverage(off)
701        )]
702        #[inline(always)]
703        unsafe fn unchecked_mul(self, rhs: usize) -> usize {
704            match self.checked_mul(rhs) {
705                Some(x) => x,
706                None => {
707                    // SAFETY: The caller promises that the multiplication will
708                    // not overflow.
709                    unsafe { core::hint::unreachable_unchecked() }
710                }
711            }
712        }
713    }
714}
715
716#[cfg(test)]
717pub(crate) mod testutil {
718    use crate::*;
719
720    /// A `T` which is aligned to at least `align_of::<A>()`.
721    #[derive(Default)]
722    pub(crate) struct Align<T, A> {
723        pub(crate) t: T,
724        _a: [A; 0],
725    }
726
727    impl<T: Default, A> Align<T, A> {
728        pub(crate) fn set_default(&mut self) {
729            self.t = T::default();
730        }
731    }
732
733    impl<T, A> Align<T, A> {
734        pub(crate) const fn new(t: T) -> Align<T, A> {
735            Align { t, _a: [] }
736        }
737    }
738
739    /// A `T` which is guaranteed not to satisfy `align_of::<A>()`.
740    ///
741    /// It must be the case that `align_of::<T>() < align_of::<A>()` in order
742    /// fot this type to work properly.
743    #[repr(C)]
744    pub(crate) struct ForceUnalign<T: Unaligned, A> {
745        // The outer struct is aligned to `A`, and, thanks to `repr(C)`, `t` is
746        // placed at the minimum offset that guarantees its alignment. If
747        // `align_of::<T>() < align_of::<A>()`, then that offset will be
748        // guaranteed *not* to satisfy `align_of::<A>()`.
749        //
750        // Note that we need `T: Unaligned` in order to guarantee that there is
751        // no padding between `_u` and `t`.
752        _u: u8,
753        pub(crate) t: T,
754        _a: [A; 0],
755    }
756
757    impl<T: Unaligned, A> ForceUnalign<T, A> {
758        pub(crate) fn new(t: T) -> ForceUnalign<T, A> {
759            ForceUnalign { _u: 0, t, _a: [] }
760        }
761    }
762    // A `u64` with alignment 8.
763    //
764    // Though `u64` has alignment 8 on some platforms, it's not guaranteed. By
765    // contrast, `AU64` is guaranteed to have alignment 8 on all platforms.
766    #[derive(
767        KnownLayout,
768        Immutable,
769        FromBytes,
770        IntoBytes,
771        Eq,
772        PartialEq,
773        Ord,
774        PartialOrd,
775        Default,
776        Debug,
777        Copy,
778        Clone,
779    )]
780    #[repr(C, align(8))]
781    pub(crate) struct AU64(pub(crate) u64);
782
783    impl AU64 {
784        // Converts this `AU64` to bytes using this platform's endianness.
785        pub(crate) fn to_bytes(self) -> [u8; 8] {
786            crate::transmute!(self)
787        }
788    }
789
790    impl Display for AU64 {
791        #[cfg_attr(
792            all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS),
793            coverage(off)
794        )]
795        fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
796            Display::fmt(&self.0, f)
797        }
798    }
799
800    #[derive(Immutable, FromBytes, Eq, PartialEq, Ord, PartialOrd, Default, Debug, Copy, Clone)]
801    #[repr(C)]
802    pub(crate) struct Nested<T, U: ?Sized> {
803        _t: T,
804        _u: U,
805    }
806}
807
808#[cfg(test)]
809mod tests {
810    use super::*;
811
812    #[test]
813    fn test_round_down_to_next_multiple_of_alignment() {
814        fn alt_impl(n: usize, align: NonZeroUsize) -> usize {
815            let mul = n / align.get();
816            mul * align.get()
817        }
818
819        for align in [1, 2, 4, 8, 16] {
820            for n in 0..256 {
821                let align = NonZeroUsize::new(align).unwrap();
822                let want = alt_impl(n, align);
823                let got = round_down_to_next_multiple_of_alignment(n, align);
824                assert_eq!(got, want, "round_down_to_next_multiple_of_alignment({}, {})", n, align);
825            }
826        }
827    }
828
829    #[rustversion::since(1.57.0)]
830    #[test]
831    #[should_panic]
832    fn test_round_down_to_next_multiple_of_alignment_zerocopy_panic_in_const_and_vec_try_reserve() {
833        round_down_to_next_multiple_of_alignment(0, NonZeroUsize::new(3).unwrap());
834    }
835}