// SPDX-License-Identifier: (BSD-2-Clause OR Apache-2.0) OR MIT
// Copyright 2023 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
#[macro_use]
pub(crate) mod macros;
#[doc(hidden)]
pub mod macro_util;
use core::{
marker::PhantomData,
mem::{self, ManuallyDrop},
num::NonZeroUsize,
ptr::NonNull,
};
use super::*;
use crate::pointer::{
invariant::{Exclusive, Shared, Valid},
SizeEq, TransmuteFromPtr,
};
/// Like [`PhantomData`], but [`Send`] and [`Sync`] regardless of whether the
/// wrapped `T` is.
pub(crate) struct SendSyncPhantomData<T: ?Sized>(PhantomData<T>);
// SAFETY: `SendSyncPhantomData` does not enable any behavior which isn't sound
// to be called from multiple threads.
unsafe impl<T: ?Sized> Send for SendSyncPhantomData<T> {}
// SAFETY: `SendSyncPhantomData` does not enable any behavior which isn't sound
// to be called from multiple threads.
unsafe impl<T: ?Sized> Sync for SendSyncPhantomData<T> {}
impl<T: ?Sized> Default for SendSyncPhantomData<T> {
fn default() -> SendSyncPhantomData<T> {
SendSyncPhantomData(PhantomData)
}
}
impl<T: ?Sized> PartialEq for SendSyncPhantomData<T> {
fn eq(&self, _other: &Self) -> bool {
true
}
}
impl<T: ?Sized> Eq for SendSyncPhantomData<T> {}
impl<T: ?Sized> Clone for SendSyncPhantomData<T> {
fn clone(&self) -> Self {
SendSyncPhantomData(PhantomData)
}
}
#[cfg(miri)]
extern "Rust" {
/// Miri-provided intrinsic that marks the pointer `ptr` as aligned to
/// `align`.
///
/// This intrinsic is used to inform Miri's symbolic alignment checker that
/// a pointer is aligned, even if Miri cannot statically deduce that fact.
/// This is often required when performing raw pointer arithmetic or casts
/// where the alignment is guaranteed by runtime checks or invariants that
/// Miri is not aware of.
pub(crate) fn miri_promise_symbolic_alignment(ptr: *const (), align: usize);
}
pub(crate) trait AsAddress {
fn addr(self) -> usize;
}
impl<T: ?Sized> AsAddress for &T {
#[inline(always)]
fn addr(self) -> usize {
let ptr: *const T = self;
AsAddress::addr(ptr)
}
}
impl<T: ?Sized> AsAddress for &mut T {
#[inline(always)]
fn addr(self) -> usize {
let ptr: *const T = self;
AsAddress::addr(ptr)
}
}
impl<T: ?Sized> AsAddress for NonNull<T> {
#[inline(always)]
fn addr(self) -> usize {
AsAddress::addr(self.as_ptr())
}
}
impl<T: ?Sized> AsAddress for *const T {
#[inline(always)]
fn addr(self) -> usize {
// FIXME(#181), FIXME(https://github.com/rust-lang/rust/issues/95228):
// Use `.addr()` instead of `as usize` once it's stable, and get rid of
// this `allow`. Currently, `as usize` is the only way to accomplish
// this.
#[allow(clippy::as_conversions)]
#[cfg_attr(
__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS,
allow(lossy_provenance_casts)
)]
return self.cast::<()>() as usize;
}
}
impl<T: ?Sized> AsAddress for *mut T {
#[inline(always)]
fn addr(self) -> usize {
let ptr: *const T = self;
AsAddress::addr(ptr)
}
}
/// Validates that `t` is aligned to `align_of::<U>()`.
#[inline(always)]
pub(crate) fn validate_aligned_to<T: AsAddress, U>(t: T) -> Result<(), AlignmentError<(), U>> {
// `mem::align_of::<U>()` is guaranteed to return a non-zero value, which in
// turn guarantees that this mod operation will not panic.
#[allow(clippy::arithmetic_side_effects)]
let remainder = t.addr() % mem::align_of::<U>();
if remainder == 0 {
Ok(())
} else {
// SAFETY: We just confirmed that `t.addr() % align_of::<U>() != 0`.
// That's only possible if `align_of::<U>() > 1`.
Err(unsafe { AlignmentError::new_unchecked(()) })
}
}
/// Returns the bytes needed to pad `len` to the next multiple of `align`.
///
/// This function assumes that align is a power of two; there are no guarantees
/// on the answer it gives if this is not the case.
#[cfg_attr(
kani,
kani::requires(len <= DstLayout::MAX_SIZE),
kani::requires(align.is_power_of_two()),
kani::ensures(|&p| (len + p) % align.get() == 0),
// Ensures that we add the minimum required padding.
kani::ensures(|&p| p < align.get()),
)]
pub(crate) const fn padding_needed_for(len: usize, align: NonZeroUsize) -> usize {
#[cfg(kani)]
#[kani::proof_for_contract(padding_needed_for)]
fn proof() {
padding_needed_for(kani::any(), kani::any());
<