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