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