// 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.
#![allow(missing_docs)]
use core::{
fmt::{Debug, Formatter},
marker::PhantomData,
};
use crate::{
pointer::{
inner::PtrInner,
invariant::*,
transmute::{MutationCompatible, SizeEq, TransmuteFromPtr},
},
AlignmentError, CastError, CastType, KnownLayout, SizeError, TryFromBytes, ValidityError,
};
/// Module used to gate access to [`Ptr`]'s fields.
mod def {
#[cfg(doc)]
use super::super::invariant;
use super::*;
/// A raw pointer with more restrictions.
///
/// `Ptr<T>` is similar to [`NonNull<T>`], but it is more restrictive in the
/// following ways (note that these requirements only hold of non-zero-sized
/// referents):
/// - It must derive from a valid allocation.
/// - It must reference a byte range which is contained inside the
/// allocation from which it derives.
/// - As a consequence, the byte range it references must have a size
/// which does not overflow `isize`.
///
/// Depending on how `Ptr` is parameterized, it may have additional
/// invariants:
/// - `ptr` conforms to the aliasing invariant of
/// [`I::Aliasing`](invariant::Aliasing).
/// - `ptr` conforms to the alignment invariant of
/// [`I::Alignment`](invariant::Alignment).
/// - `ptr` conforms to the validity invariant of
/// [`I::Validity`](invariant::Validity).
///
/// `Ptr<'a, T>` is [covariant] in `'a` and invariant in `T`.
///
/// [`NonNull<T>`]: core::ptr::NonNull
/// [covariant]: https://doc.rust-lang.org/reference/subtyping.html
pub struct Ptr<'a, T, I>
where
T: ?Sized,
I: Invariants,
{
/// # Invariants
///
/// 0. `ptr` conforms to the aliasing invariant of
/// [`I::Aliasing`](invariant::Aliasing).
/// 1. `ptr` conforms to the alignment invariant of
/// [`I::Alignment`](invariant::Alignment).
/// 2. `ptr` conforms to the validity invariant of
/// [`I::Validity`](invariant::Validity).
// SAFETY: `PtrInner<'a, T>` is covariant in `'a` and invariant in `T`.
ptr: PtrInner<'a, T>,
_invariants: PhantomData<I>,
}
impl<'a, T, I> Ptr<'a, T, I>
where
T: 'a + ?Sized,
I: Invariants,
{
/// Constructs a new `Ptr` from a [`PtrInner`].
///
/// # Safety
///
/// The caller promises that:
///
/// 0. `ptr` conforms to the aliasing invariant of
/// [`I::Aliasing`](invariant::Aliasing).
/// 1. `ptr` conforms to the alignment invariant of
/// [`I::Alignment`](invariant::Alignment).
/// 2. `ptr` conforms to the validity invariant of
/// [`I::Validity`](invariant::Validity).
pub(crate) unsafe fn from_inner(ptr: PtrInner<'a, T>) -> Ptr<'a, T, I> {
// SAFETY: The caller has promised to satisfy all safety invariants
// of `Ptr`.
Self { ptr, _invariants: PhantomData }
}
/// Converts this `Ptr<T>` to a [`PtrInner<T>`].
///
/// Note that this method does not consume `self`. The caller should
/// watch out for `unsafe` code which uses the returned value in a way
/// that violates the safety invariants of `self`.
#[inline]
#[must_use]
pub fn as_inner(&self) -> PtrInner<'a, T> {
self.ptr
}
}
}
#[allow(unreachable_pub)] // This is a false positive on our MSRV toolchain.
pub use def::Ptr;
/// External trait implementations on [`Ptr`].
mod _external {
use super::*;
/// SAFETY: Shared pointers are safely `Copy`. `Ptr`'s other invariants
/// (besides aliasing) are unaffected by the number of references that exist
/// to `Ptr`'s referent. The notable cases are:
/// - Alignment is a property of the referent type (`T`) and the address,
/// both of which are unchanged
/// - Let `S(T, V)` be the set of bit values permitted to appear in the
/// referent of a `Ptr<T, I: Invariants<Validity = V>>`. Since this copy
/// does not change `I::Validity` or `T`, `S(T, I::Validity)` is also
/// unchanged.
///
/// We are required to guarantee that the referents of the original `Ptr`
/// and of the copy (which, of course, are actually the same since they
/// live in the same byte address range) both remain in the set `S(T,
/// I::Validity)`. Since this invariant holds on the original `Ptr`, it
/// cannot be violated by the original `Ptr`, and thus the original `Ptr`
/// cannot be used to violate this invariant on the copy. The inverse
/// holds as well.
impl<
|