#![doc = include_str!("../README.md")]1#![no_std]2#![cfg_attr(docsrs, feature(doc_auto_cfg))]3#![expect(unsafe_code, reason = "Raw pointers are inherently unsafe.")]4#![doc(5html_logo_url = "https://bevy.org/assets/icon.png",6html_favicon_url = "https://bevy.org/assets/icon.png"7)]89use core::{10cell::UnsafeCell,11fmt::{self, Debug, Formatter, Pointer},12marker::PhantomData,13mem::{self, ManuallyDrop, MaybeUninit},14num::NonZeroUsize,15ptr::{self, NonNull},16};1718/// Used as a type argument to [`Ptr`], [`PtrMut`], [`OwningPtr`], and [`MovingPtr`] to specify that the pointer is guaranteed19/// to be [aligned].20///21/// [aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment22#[derive(Debug, Copy, Clone)]23pub struct Aligned;2425/// Used as a type argument to [`Ptr`], [`PtrMut`], [`OwningPtr`], and [`MovingPtr`] to specify that the pointer may not [aligned].26///27/// [aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment28#[derive(Debug, Copy, Clone)]29pub struct Unaligned;3031/// Trait that is only implemented for [`Aligned`] and [`Unaligned`] to work around the lack of ability32/// to have const generics of an enum.33pub trait IsAligned: sealed::Sealed {34/// Reads the value pointed to by `ptr`.35///36/// # Safety37/// - `ptr` must be valid for reads.38/// - `ptr` must point to a valid instance of type `T`39/// - If this type is [`Aligned`], then `ptr` must be [properly aligned] for type `T`.40///41/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment42#[doc(hidden)]43unsafe fn read_ptr<T>(ptr: *const T) -> T;4445/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source46/// and destination must *not* overlap.47///48/// # Safety49/// - `src` must be valid for reads of `count * size_of::<T>()` bytes.50/// - `dst` must be valid for writes of `count * size_of::<T>()` bytes.51/// - The region of memory beginning at `src` with a size of `count *52/// size_of::<T>()` bytes must *not* overlap with the region of memory53/// beginning at `dst` with the same size.54/// - If this type is [`Aligned`], then both `src` and `dst` must properly55/// be aligned for values of type `T`.56#[doc(hidden)]57unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);5859/// Reads the value pointed to by `ptr`.60///61/// # Safety62/// - `ptr` must be valid for reads and writes.63/// - `ptr` must point to a valid instance of type `T`64/// - If this type is [`Aligned`], then `ptr` must be [properly aligned] for type `T`.65/// - The value pointed to by `ptr` must be valid for dropping.66/// - While `drop_in_place` is executing, the only way to access parts of `ptr` is through67/// the `&mut Self` supplied to it's `Drop::drop` impl.68///69/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment70#[doc(hidden)]71unsafe fn drop_in_place<T>(ptr: *mut T);72}7374impl IsAligned for Aligned {75#[inline]76unsafe fn read_ptr<T>(ptr: *const T) -> T {77// SAFETY:78// - The caller is required to ensure that `src` must be valid for reads.79// - The caller is required to ensure that `src` points to a valid instance of type `T`.80// - This type is `Aligned` so the caller must ensure that `src` is properly aligned for type `T`.81unsafe { ptr.read() }82}8384#[inline]85unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {86// SAFETY:87// - The caller is required to ensure that `src` must be valid for reads.88// - The caller is required to ensure that `dst` must be valid for writes.89// - The caller is required to ensure that `src` and `dst` are aligned.90// - The caller is required to ensure that the memory region covered by `src`91// and `dst`, fitting up to `count` elements do not overlap.92unsafe {93ptr::copy_nonoverlapping(src, dst, count);94}95}9697#[inline]98unsafe fn drop_in_place<T>(ptr: *mut T) {99// SAFETY:100// - The caller is required to ensure that `ptr` must be valid for reads and writes.101// - The caller is required to ensure that `ptr` points to a valid instance of type `T`.102// - This type is `Aligned` so the caller must ensure that `ptr` is properly aligned for type `T`.103// - The caller is required to ensure that `ptr` points must be valid for dropping.104// - The caller is required to ensure that the value `ptr` points must not be used after this function105// call.106unsafe { ptr::drop_in_place(ptr) };107}108}109110impl IsAligned for Unaligned {111#[inline]112unsafe fn read_ptr<T>(ptr: *const T) -> T {113// SAFETY:114// - The caller is required to ensure that `src` must be valid for reads.115// - The caller is required to ensure that `src` points to a valid instance of type `T`.116unsafe { ptr.read_unaligned() }117}118119#[inline]120unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {121// SAFETY:122// - The caller is required to ensure that `src` must be valid for reads.123// - The caller is required to ensure that `dst` must be valid for writes.124// - This is doing a byte-wise copy. `src` and `dst` are always guaranteed to be125// aligned.126// - The caller is required to ensure that the memory region covered by `src`127// and `dst`, fitting up to `count` elements do not overlap.128unsafe {129ptr::copy_nonoverlapping::<u8>(130src.cast::<u8>(),131dst.cast::<u8>(),132count * size_of::<T>(),133);134}135}136137#[inline]138unsafe fn drop_in_place<T>(ptr: *mut T) {139// SAFETY:140// - The caller is required to ensure that `ptr` must be valid for reads and writes.141// - The caller is required to ensure that `ptr` points to a valid instance of type `T`.142// - This type is not `Aligned` so the caller does not need to ensure that `ptr` is properly aligned for type `T`.143// - The caller is required to ensure that `ptr` points must be valid for dropping.144// - The caller is required to ensure that the value `ptr` points must not be used after this function145// call.146unsafe { drop(ptr.read_unaligned()) }147}148}149150mod sealed {151pub trait Sealed {}152impl Sealed for super::Aligned {}153impl Sealed for super::Unaligned {}154}155156/// A newtype around [`NonNull`] that only allows conversion to read-only borrows or pointers.157///158/// This type can be thought of as the `*const T` to [`NonNull<T>`]'s `*mut T`.159#[repr(transparent)]160pub struct ConstNonNull<T: ?Sized>(NonNull<T>);161162impl<T: ?Sized> ConstNonNull<T> {163/// Creates a new `ConstNonNull` if `ptr` is non-null.164///165/// # Examples166///167/// ```168/// use bevy_ptr::ConstNonNull;169///170/// let x = 0u32;171/// let ptr = ConstNonNull::<u32>::new(&x as *const _).expect("ptr is null!");172///173/// if let Some(ptr) = ConstNonNull::<u32>::new(core::ptr::null()) {174/// unreachable!();175/// }176/// ```177pub fn new(ptr: *const T) -> Option<Self> {178NonNull::new(ptr.cast_mut()).map(Self)179}180181/// Creates a new `ConstNonNull`.182///183/// # Safety184///185/// `ptr` must be non-null.186///187/// # Examples188///189/// ```190/// use bevy_ptr::ConstNonNull;191///192/// let x = 0u32;193/// let ptr = unsafe { ConstNonNull::new_unchecked(&x as *const _) };194/// ```195///196/// *Incorrect* usage of this function:197///198/// ```rust,no_run199/// use bevy_ptr::ConstNonNull;200///201/// // NEVER DO THAT!!! This is undefined behavior. ⚠️202/// let ptr = unsafe { ConstNonNull::<u32>::new_unchecked(core::ptr::null()) };203/// ```204pub const unsafe fn new_unchecked(ptr: *const T) -> Self {205// SAFETY: This function's safety invariants are identical to `NonNull::new_unchecked`206// The caller must satisfy all of them.207unsafe { Self(NonNull::new_unchecked(ptr.cast_mut())) }208}209210/// Returns a shared reference to the value.211///212/// # Safety213///214/// When calling this method, you have to ensure that all of the following is true:215///216/// * The pointer must be [properly aligned].217///218/// * It must be "dereferenceable" in the sense defined in [the module documentation].219///220/// * The pointer must point to an initialized instance of `T`.221///222/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is223/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.224/// In particular, while this reference exists, the memory the pointer points to must225/// not get mutated (except inside `UnsafeCell`).226///227/// This applies even if the result of this method is unused!228/// (The part about being initialized is not yet fully decided, but until229/// it is, the only safe approach is to ensure that they are indeed initialized.)230///231/// # Examples232///233/// ```234/// use bevy_ptr::ConstNonNull;235///236/// let mut x = 0u32;237/// let ptr = ConstNonNull::new(&mut x as *mut _).expect("ptr is null!");238///239/// let ref_x = unsafe { ptr.as_ref() };240/// println!("{ref_x}");241/// ```242///243/// [the module documentation]: core::ptr#safety244/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment245#[inline]246pub unsafe fn as_ref<'a>(&self) -> &'a T {247// SAFETY: This function's safety invariants are identical to `NonNull::as_ref`248// The caller must satisfy all of them.249unsafe { self.0.as_ref() }250}251}252253impl<T: ?Sized> From<NonNull<T>> for ConstNonNull<T> {254fn from(value: NonNull<T>) -> ConstNonNull<T> {255ConstNonNull(value)256}257}258259impl<'a, T: ?Sized> From<&'a T> for ConstNonNull<T> {260fn from(value: &'a T) -> ConstNonNull<T> {261ConstNonNull(NonNull::from(value))262}263}264265impl<'a, T: ?Sized> From<&'a mut T> for ConstNonNull<T> {266fn from(value: &'a mut T) -> ConstNonNull<T> {267ConstNonNull(NonNull::from(value))268}269}270271/// Type-erased borrow of some unknown type chosen when constructing this type.272///273/// This type tries to act "borrow-like" which means that:274/// - It should be considered immutable: its target must not be changed while this pointer is alive.275/// - It must always point to a valid value of whatever the pointee type is.276/// - The lifetime `'a` accurately represents how long the pointer is valid for.277/// - If `A` is [`Aligned`], the pointer must always be [properly aligned] for the unknown pointee type.278///279/// It may be helpful to think of this type as similar to `&'a dyn Any` but without280/// the metadata and able to point to data that does not correspond to a Rust type.281///282/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment283#[derive(Copy, Clone)]284#[repr(transparent)]285pub struct Ptr<'a, A: IsAligned = Aligned>(NonNull<u8>, PhantomData<(&'a u8, A)>);286287/// Type-erased mutable borrow of some unknown type chosen when constructing this type.288///289/// This type tries to act "borrow-like" which means that:290/// - Pointer is considered exclusive and mutable. It cannot be cloned as this would lead to291/// aliased mutability.292/// - It must always point to a valid value of whatever the pointee type is.293/// - The lifetime `'a` accurately represents how long the pointer is valid for.294/// - If `A` is [`Aligned`], the pointer must always be [properly aligned] for the unknown pointee type.295///296/// It may be helpful to think of this type as similar to `&'a mut dyn Any` but without297/// the metadata and able to point to data that does not correspond to a Rust type.298///299/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment300#[repr(transparent)]301pub struct PtrMut<'a, A: IsAligned = Aligned>(NonNull<u8>, PhantomData<(&'a mut u8, A)>);302303/// Type-erased [`Box`]-like pointer to some unknown type chosen when constructing this type.304///305/// Conceptually represents ownership of whatever data is being pointed to and so is306/// responsible for calling its `Drop` impl. This pointer is _not_ responsible for freeing307/// the memory pointed to by this pointer as it may be pointing to an element in a `Vec` or308/// to a local in a function etc.309///310/// This type tries to act "borrow-like" which means that:311/// - Pointer should be considered exclusive and mutable. It cannot be cloned as this would lead312/// to aliased mutability and potentially use after free bugs.313/// - It must always point to a valid value of whatever the pointee type is.314/// - The lifetime `'a` accurately represents how long the pointer is valid for.315/// - If `A` is [`Aligned`], the pointer must always be [properly aligned] for the unknown pointee type.316///317/// It may be helpful to think of this type as similar to `&'a mut ManuallyDrop<dyn Any>` but318/// without the metadata and able to point to data that does not correspond to a Rust type.319///320/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment321/// [`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html322#[repr(transparent)]323pub struct OwningPtr<'a, A: IsAligned = Aligned>(NonNull<u8>, PhantomData<(&'a mut u8, A)>);324325/// A [`Box`]-like pointer for moving a value to a new memory location without needing to pass by326/// value.327///328/// Conceptually represents ownership of whatever data is being pointed to and will call its329/// [`Drop`] impl upon being dropped. This pointer is _not_ responsible for freeing330/// the memory pointed to by this pointer as it may be pointing to an element in a `Vec` or331/// to a local in a function etc.332///333/// This type tries to act "borrow-like" which means that:334/// - Pointer should be considered exclusive and mutable. It cannot be cloned as this would lead335/// to aliased mutability and potentially use after free bugs.336/// - It must always point to a valid value of whatever the pointee type is.337/// - The lifetime `'a` accurately represents how long the pointer is valid for.338/// - It does not support pointer arithmetic in any way.339/// - If `A` is [`Aligned`], the pointer must always be [properly aligned] for the type `T`.340///341/// A value can be deconstructed into its fields via [`deconstruct_moving_ptr`], see it's documentation342/// for an example on how to use it.343///344/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment345/// [`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html346#[repr(transparent)]347pub struct MovingPtr<'a, T, A: IsAligned = Aligned>(NonNull<T>, PhantomData<(&'a mut T, A)>);348349macro_rules! impl_ptr {350($ptr:ident) => {351impl<'a> $ptr<'a, Aligned> {352/// Removes the alignment requirement of this pointer353pub fn to_unaligned(self) -> $ptr<'a, Unaligned> {354$ptr(self.0, PhantomData)355}356}357358impl<'a, A: IsAligned> From<$ptr<'a, A>> for NonNull<u8> {359fn from(ptr: $ptr<'a, A>) -> Self {360ptr.0361}362}363364impl<A: IsAligned> $ptr<'_, A> {365/// Calculates the offset from a pointer.366/// As the pointer is type-erased, there is no size information available. The provided367/// `count` parameter is in raw bytes.368///369/// *See also: [`ptr::offset`][ptr_offset]*370///371/// # Safety372/// - The offset cannot make the existing ptr null, or take it out of bounds for its allocation.373/// - If the `A` type parameter is [`Aligned`] then the offset must not make the resulting pointer374/// be unaligned for the pointee type.375/// - The value pointed by the resulting pointer must outlive the lifetime of this pointer.376///377/// [ptr_offset]: https://doc.rust-lang.org/std/primitive.pointer.html#method.offset378#[inline]379pub unsafe fn byte_offset(self, count: isize) -> Self {380Self(381// SAFETY: The caller upholds safety for `offset` and ensures the result is not null.382unsafe { NonNull::new_unchecked(self.as_ptr().offset(count)) },383PhantomData,384)385}386387/// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).388/// As the pointer is type-erased, there is no size information available. The provided389/// `count` parameter is in raw bytes.390///391/// *See also: [`ptr::add`][ptr_add]*392///393/// # Safety394/// - The offset cannot make the existing ptr null, or take it out of bounds for its allocation.395/// - If the `A` type parameter is [`Aligned`] then the offset must not make the resulting pointer396/// be unaligned for the pointee type.397/// - The value pointed by the resulting pointer must outlive the lifetime of this pointer.398///399/// [ptr_add]: https://doc.rust-lang.org/std/primitive.pointer.html#method.add400#[inline]401pub unsafe fn byte_add(self, count: usize) -> Self {402Self(403// SAFETY: The caller upholds safety for `add` and ensures the result is not null.404unsafe { NonNull::new_unchecked(self.as_ptr().add(count)) },405PhantomData,406)407}408}409410impl<A: IsAligned> Pointer for $ptr<'_, A> {411#[inline]412fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {413Pointer::fmt(&self.0, f)414}415}416417impl Debug for $ptr<'_, Aligned> {418#[inline]419fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {420write!(f, "{}<Aligned>({:?})", stringify!($ptr), self.0)421}422}423424impl Debug for $ptr<'_, Unaligned> {425#[inline]426fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {427write!(f, "{}<Unaligned>({:?})", stringify!($ptr), self.0)428}429}430};431}432433impl_ptr!(Ptr);434impl_ptr!(PtrMut);435impl_ptr!(OwningPtr);436437impl<'a, T> MovingPtr<'a, T, Aligned> {438/// Removes the alignment requirement of this pointer439#[inline]440pub fn to_unaligned(self) -> MovingPtr<'a, T, Unaligned> {441let value = MovingPtr(self.0, PhantomData);442mem::forget(self);443value444}445446/// Consumes a value and creates an [`MovingPtr`] to it while ensuring a double drop does not happen.447#[inline]448pub fn make<F: FnOnce(MovingPtr<'_, T>) -> R, R>(val: T, f: F) -> R {449let mut val = MaybeUninit::new(val);450// SAFETY: The value behind the pointer will not get dropped or observed later.451f(unsafe { MovingPtr::from_value(&mut val) })452}453454/// Creates a [`MovingPtr`] from a provided value of type `T`.455///456/// # Safety457/// - `value` must store a properly initialized value of type `T`.458/// - Once the returned [`MovingPtr`] has been used, `value` must be treated as459/// it were uninitialized unless it was explicitly leaked via [`core::mem::forget`].460#[inline]461pub unsafe fn from_value(value: &'a mut MaybeUninit<T>) -> Self {462// SAFETY:463// - MaybeUninit<T> has the same memory layout as T464// - The caller guarantees that `value` must point to a valid instance of type `T`.465MovingPtr(NonNull::from(value).cast::<T>(), PhantomData)466}467}468469impl<'a, T, A: IsAligned> MovingPtr<'_, T, A> {470/// Creates a new instance from a raw pointer.471///472/// # Safety473/// - `inner` must point to valid value of `T`.474/// - If the `A` type parameter is [`Aligned`] then `inner` must be be [properly aligned] for `T`.475/// - `inner` must have correct provenance to allow read and writes of the pointee type.476/// - The lifetime `'a` must be constrained such that this [`MovingPtr`] will stay valid and nothing477/// else can read or mutate the pointee while this [`MovingPtr`] is live.478///479/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment480#[inline]481pub unsafe fn new(inner: NonNull<T>) -> Self {482Self(inner, PhantomData)483}484485/// Partially moves out some fields inside of `self`.486///487/// The partially returned value is returned back pointing to `MaybeUninit<T>`.488///489/// # Safety490/// - The call into `f` must not complete having dropped the provided pointer.491/// - The fields moved out of in `f` must not be accessed or dropped after this function returns.492///493/// As a result, it is strongly recommended to call [`forget`] on the provided pointer once the494/// partial deconstruction has completed.495///496/// # Example497///498/// ```499/// use core::mem::{offset_of, MaybeUninit};500/// use bevy_ptr::MovingPtr;501/// # use bevy_ptr::Unaligned;502/// # struct FieldAType(usize);503/// # struct FieldBType(usize);504/// # struct FieldCType(usize);505/// # fn insert<T>(_ptr: MovingPtr<'_, T, Unaligned>) {}506///507/// struct Parent {508/// field_a: FieldAType,509/// field_b: FieldBType,510/// field_c: FieldCType,511/// }512///513/// # let parent = Parent {514/// # field_a: FieldAType(0),515/// # field_b: FieldBType(0),516/// # field_c: FieldCType(0),517/// # };518///519/// MovingPtr::make(parent, |parent_ptr| unsafe {520/// // SAFETY:521/// // - It is impossible for the provided closure to drop the provided pointer as `move_field` cannot panic.522/// // - `field_a` and `field_b` are moved out of but never accessed after this.523/// let partial_parent = MovingPtr::partial_move(parent_ptr, |parent_ptr| {524/// bevy_ptr::deconstruct_moving_ptr!(parent_ptr, Parent {525/// field_a: FieldAType => { insert(field_a) },526/// field_b: FieldBType => { insert(field_b) },527/// });528/// });529///530/// // Move the rest of fields out of the parent.531/// bevy_ptr::deconstruct_moving_ptr!(partial_parent, Parent {532/// field_c: FieldBType => { insert(field_c) },533/// });534/// });535/// ```536///537/// [`forget`]: core::mem::forget538#[inline]539pub unsafe fn partial_move(540ptr: MovingPtr<'a, T, A>,541f: impl FnOnce(MovingPtr<'a, T, A>),542) -> MovingPtr<'a, MaybeUninit<T>, A> {543let partial_ptr = ptr.0;544f(ptr);545MovingPtr(partial_ptr.cast::<MaybeUninit<T>>(), PhantomData)546}547548/// Reads the value pointed to by this pointer.549#[inline]550pub fn read(self) -> T {551// SAFETY:552// - `self.0` must be valid for reads as this type owns the value it points to.553// - `self.0` must always point to a valid instance of type `T`554// - If `A` is [`Aligned`], then `ptr` must be properly aligned for type `T`.555let value = unsafe { A::read_ptr(self.0.as_ptr()) };556mem::forget(self);557value558}559560/// Writes the value pointed to by this pointer to a provided location.561///562/// This does *not* drop the value stored at `dst` and it's the caller's responsibility563/// to ensure that it's properly dropped.564///565/// # Safety566/// - `dst` must be valid for writes.567/// - If the `A` type parameter is [`Aligned`] then `dst` must be [properly aligned] for `T`.568///569/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment570#[inline]571pub unsafe fn write_to(self, dst: *mut T) {572let src = self.0.as_ptr();573mem::forget(self);574// SAFETY:575// - `src` must be valid for reads as this pointer is considered to own the value it points to.576// - The caller is required to ensure that `dst` must be valid for writes.577// - As `A` is `Aligned`, the caller is required to ensure that `dst` is aligned and `src` must578// be aligned by the type's invariants.579unsafe { A::copy_nonoverlapping(src, dst, 1) };580}581582/// Writes the value pointed to by this pointer into `dst`.583///584/// The value previously stored at `dst` will be dropped.585#[inline]586pub fn assign_to(self, dst: &mut T) {587// SAFETY:588// - `dst` is a mutable borrow, it must point to a valid instance of `T`.589// - `dst` is a mutable borrow, it must point to value that is valid for dropping.590// - `dst` is a mutable borrow, it must not alias any other access.591unsafe {592ptr::drop_in_place(dst);593}594// SAFETY:595// - `dst` is a mutable borrow, it must be valid for writes.596// - `dst` is a mutable borrow, it must always be aligned.597unsafe {598self.write_to(dst);599}600}601602/// Creates a [`MovingPtr`] for a specific field within `self`. This is a building block for603/// [`deconstruct_moving_ptr`] and should generally not be accessed directly.604///605/// This function is explicitly made for deconstructive moves.606///607/// The correct `byte_offset` for a field can be obtained via [`core::mem::offset_of`].608///609/// The returned value will always be considered unaligned as `repr(packed)` types may result in610/// unaligned fields. The pointer is convertible back into an aligned one using the [`TryFrom`] impl.611///612/// # Safety613/// - `U` must be the correct type for the field at `byte_offset` within `self`.614/// - `self` should not be accessed or dropped as if it were a complete value.615/// Other fields that have not been moved out of may still be accessed or dropped separately.616/// - This function cannot alias the field with any other access, including other calls to [`move_field`]617/// for the same field, without first calling [`forget`] on it first.618///619/// A result of the above invariants means that any operation that could cause `self` to be dropped while620/// the pointers to the fields are held will result in undefined behavior. This requires exctra caution621/// around code that may panic. See the example below for an example of how to safely use this function.622///623/// # Example624///625/// ```626/// use core::mem::offset_of;627/// use bevy_ptr::MovingPtr;628/// # use bevy_ptr::Unaligned;629/// # struct FieldAType(usize);630/// # struct FieldBType(usize);631/// # struct FieldCType(usize);632/// # fn insert<T>(_ptr: MovingPtr<'_, T, Unaligned>) {}633///634/// struct Parent {635/// field_a: FieldAType,636/// field_b: FieldBType,637/// field_c: FieldCType,638/// }639///640/// # let parent = Parent {641/// # field_a: FieldAType(0),642/// # field_b: FieldBType(0),643/// # field_c: FieldCType(0),644/// # };645///646/// MovingPtr::make(parent, |parent_ptr| unsafe {647/// let field_a = parent_ptr.move_field::<FieldAType>(offset_of!(Parent, field_a));648/// let field_b = parent_ptr.move_field::<FieldBType>(offset_of!(Parent, field_b));649/// let field_c = parent_ptr.move_field::<FieldCType>(offset_of!(Parent, field_c));650/// // Each call to insert may panic! Ensure that `parent_ptr` cannot be dropped before651/// // calling them!652/// core::mem::forget(parent_ptr);653/// insert(field_a);654/// insert(field_b);655/// insert(field_c);656/// });657/// ```658///659/// [`forget`]: core::mem::forget660/// [`move_field`]: Self::move_field661#[inline]662#[doc(hidden)]663pub unsafe fn move_field<U>(&self, byte_offset: usize) -> MovingPtr<'a, U, Unaligned> {664MovingPtr(665// SAFETY: The caller must ensure that `U` is the correct type for the field at `byte_offset`.666unsafe { self.0.byte_add(byte_offset) }.cast::<U>(),667PhantomData,668)669}670}671672impl<'a, T, A: IsAligned> MovingPtr<'a, MaybeUninit<T>, A> {673/// Creates a [`MovingPtr`] pointing to a valid instance of `T`.674///675/// See also: [`MaybeUninit::assume_init`].676///677/// # Safety678/// It's up to the caller to ensure that the value pointed to by `self`679/// is really in an initialized state. Calling this when the content is not yet680/// fully initialized causes immediate undefined behavior.681#[inline]682pub unsafe fn assume_init(self) -> MovingPtr<'a, T, A> {683let value = MovingPtr(self.0.cast::<T>(), PhantomData);684mem::forget(self);685value686}687}688689impl<T, A: IsAligned> Pointer for MovingPtr<'_, T, A> {690#[inline]691fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {692Pointer::fmt(&self.0, f)693}694}695696impl<T> Debug for MovingPtr<'_, T, Aligned> {697#[inline]698fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {699write!(f, "{}<Aligned>({:?})", stringify!($ptr), self.0)700}701}702703impl<T> Debug for MovingPtr<'_, T, Unaligned> {704#[inline]705fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {706write!(f, "{}<Unaligned>({:?})", stringify!($ptr), self.0)707}708}709710impl<'a, T, A: IsAligned> From<MovingPtr<'a, T, A>> for OwningPtr<'a, A> {711#[inline]712fn from(value: MovingPtr<'a, T, A>) -> Self {713// SAFETY:714// - `value.0` must always point to valid value of type `T`.715// - The type parameter `A` is mirrored from input to output, keeping the same alignment guarantees.716// - `value.0` by construction must have correct provenance to allow read and writes of type `T`.717// - The lifetime `'a` is mirrored from input to output, keeping the same lifetime guarantees.718// - `OwningPtr` maintains the same aliasing invariants as `MovingPtr`.719let ptr = unsafe { OwningPtr::new(value.0.cast::<u8>()) };720mem::forget(value);721ptr722}723}724725impl<'a, T> TryFrom<MovingPtr<'a, T, Unaligned>> for MovingPtr<'a, T, Aligned> {726type Error = MovingPtr<'a, T, Unaligned>;727#[inline]728fn try_from(value: MovingPtr<'a, T, Unaligned>) -> Result<Self, Self::Error> {729let ptr = value.0;730if ptr.as_ptr().is_aligned() {731Ok(MovingPtr(ptr, PhantomData))732} else {733Err(value)734}735}736}737738impl<T, A: IsAligned> Drop for MovingPtr<'_, T, A> {739fn drop(&mut self) {740// SAFETY:741// - `self.0` must be valid for reads and writes as this pointer type owns the value it points to.742// - `self.0` must always point to a valid instance of type `T`743// - If `A` is `Aligned`, then `ptr` must be properly aligned for type `T` by construction.744// - `self.0` owns the value it points to so it must always be valid for dropping until this pointer is dropped.745// - This type owns the value it points to, so it's required to not mutably alias value that it points to.746unsafe { A::drop_in_place(self.0.as_ptr()) };747}748}749750impl<'a, A: IsAligned> Ptr<'a, A> {751/// Creates a new instance from a raw pointer.752///753/// # Safety754/// - `inner` must point to valid value of whatever the pointee type is.755/// - If the `A` type parameter is [`Aligned`] then `inner` must be be [properly aligned]for the pointee type.756/// - `inner` must have correct provenance to allow reads of the pointee type.757/// - The lifetime `'a` must be constrained such that this [`Ptr`] will stay valid and nothing758/// can mutate the pointee while this [`Ptr`] is live except through an [`UnsafeCell`].759///760/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment761#[inline]762pub unsafe fn new(inner: NonNull<u8>) -> Self {763Self(inner, PhantomData)764}765766/// Transforms this [`Ptr`] into an [`PtrMut`]767///768/// # Safety769/// * The data pointed to by this `Ptr` must be valid for writes.770/// * There must be no active references (mutable or otherwise) to the data underlying this `Ptr`.771/// * Another [`PtrMut`] for the same [`Ptr`] must not be created until the first is dropped.772#[inline]773pub unsafe fn assert_unique(self) -> PtrMut<'a, A> {774PtrMut(self.0, PhantomData)775}776777/// Transforms this [`Ptr<T>`] into a `&T` with the same lifetime778///779/// # Safety780/// - `T` must be the erased pointee type for this [`Ptr`].781/// - If the type parameter `A` is [`Unaligned`] then this pointer must be be [properly aligned]782/// for the pointee type `T`.783///784/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment785#[inline]786pub unsafe fn deref<T>(self) -> &'a T {787let ptr = self.as_ptr().cast::<T>().debug_ensure_aligned();788// SAFETY: The caller ensures the pointee is of type `T` and the pointer can be dereferenced.789unsafe { &*ptr }790}791792/// Gets the underlying pointer, erasing the associated lifetime.793///794/// If possible, it is strongly encouraged to use [`deref`](Self::deref) over this function,795/// as it retains the lifetime.796#[inline]797pub fn as_ptr(self) -> *mut u8 {798self.0.as_ptr()799}800}801802impl<'a, T: ?Sized> From<&'a T> for Ptr<'a> {803#[inline]804fn from(val: &'a T) -> Self {805// SAFETY: The returned pointer has the same lifetime as the passed reference.806// Access is immutable.807unsafe { Self::new(NonNull::from(val).cast()) }808}809}810811impl<'a, A: IsAligned> PtrMut<'a, A> {812/// Creates a new instance from a raw pointer.813///814/// # Safety815/// - `inner` must point to valid value of whatever the pointee type is.816/// - If the `A` type parameter is [`Aligned`] then `inner` must be be [properly aligned] for the pointee type.817/// - `inner` must have correct provenance to allow read and writes of the pointee type.818/// - The lifetime `'a` must be constrained such that this [`PtrMut`] will stay valid and nothing819/// else can read or mutate the pointee while this [`PtrMut`] is live.820///821/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment822#[inline]823pub unsafe fn new(inner: NonNull<u8>) -> Self {824Self(inner, PhantomData)825}826827/// Transforms this [`PtrMut`] into an [`OwningPtr`]828///829/// # Safety830/// Must have right to drop or move out of [`PtrMut`].831#[inline]832pub unsafe fn promote(self) -> OwningPtr<'a, A> {833OwningPtr(self.0, PhantomData)834}835836/// Transforms this [`PtrMut<T>`] into a `&mut T` with the same lifetime837///838/// # Safety839/// - `T` must be the erased pointee type for this [`PtrMut`].840/// - If the type parameter `A` is [`Unaligned`] then this pointer must be be [properly aligned]841/// for the pointee type `T`.842///843/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment844#[inline]845pub unsafe fn deref_mut<T>(self) -> &'a mut T {846let ptr = self.as_ptr().cast::<T>().debug_ensure_aligned();847// SAFETY: The caller ensures the pointee is of type `T` and the pointer can be dereferenced.848unsafe { &mut *ptr }849}850851/// Gets the underlying pointer, erasing the associated lifetime.852///853/// If possible, it is strongly encouraged to use [`deref_mut`](Self::deref_mut) over854/// this function, as it retains the lifetime.855#[inline]856pub fn as_ptr(&self) -> *mut u8 {857self.0.as_ptr()858}859860/// Gets a [`PtrMut`] from this with a smaller lifetime.861#[inline]862pub fn reborrow(&mut self) -> PtrMut<'_, A> {863// SAFETY: the ptrmut we're borrowing from is assumed to be valid864unsafe { PtrMut::new(self.0) }865}866867/// Gets an immutable reference from this mutable reference868#[inline]869pub fn as_ref(&self) -> Ptr<'_, A> {870// SAFETY: The `PtrMut` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees871unsafe { Ptr::new(self.0) }872}873}874875impl<'a, T: ?Sized> From<&'a mut T> for PtrMut<'a> {876#[inline]877fn from(val: &'a mut T) -> Self {878// SAFETY: The returned pointer has the same lifetime as the passed reference.879// The reference is mutable, and thus will not alias.880unsafe { Self::new(NonNull::from(val).cast()) }881}882}883884impl<'a> OwningPtr<'a> {885/// This exists mostly to reduce compile times;886/// code is only duplicated per type, rather than per function called.887///888/// # Safety889///890/// Safety constraints of [`PtrMut::promote`] must be upheld.891unsafe fn make_internal<T>(temp: &mut ManuallyDrop<T>) -> OwningPtr<'_> {892// SAFETY: The constraints of `promote` are upheld by caller.893unsafe { PtrMut::from(&mut *temp).promote() }894}895896/// Consumes a value and creates an [`OwningPtr`] to it while ensuring a double drop does not happen.897#[inline]898pub fn make<T, F: FnOnce(OwningPtr<'_>) -> R, R>(val: T, f: F) -> R {899let mut val = ManuallyDrop::new(val);900// SAFETY: The value behind the pointer will not get dropped or observed later,901// so it's safe to promote it to an owning pointer.902f(unsafe { Self::make_internal(&mut val) })903}904}905906impl<'a, A: IsAligned> OwningPtr<'a, A> {907/// Creates a new instance from a raw pointer.908///909/// # Safety910/// - `inner` must point to valid value of whatever the pointee type is.911/// - If the `A` type parameter is [`Aligned`] then `inner` must be [properly aligned] for the pointee type.912/// - `inner` must have correct provenance to allow read and writes of the pointee type.913/// - The lifetime `'a` must be constrained such that this [`OwningPtr`] will stay valid and nothing914/// else can read or mutate the pointee while this [`OwningPtr`] is live.915///916/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment917#[inline]918pub unsafe fn new(inner: NonNull<u8>) -> Self {919Self(inner, PhantomData)920}921922/// Consumes the [`OwningPtr`] to obtain ownership of the underlying data of type `T`.923///924/// # Safety925/// - `T` must be the erased pointee type for this [`OwningPtr`].926/// - If the type parameter `A` is [`Unaligned`] then this pointer must be be [properly aligned]927/// for the pointee type `T`.928///929/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment930#[inline]931pub unsafe fn read<T>(self) -> T {932let ptr = self.as_ptr().cast::<T>().debug_ensure_aligned();933// SAFETY: The caller ensure the pointee is of type `T` and uphold safety for `read`.934unsafe { ptr.read() }935}936937/// Casts to a concrete type as a [`MovingPtr`].938///939/// # Safety940/// - `T` must be the erased pointee type for this [`OwningPtr`].941#[inline]942pub unsafe fn cast<T>(self) -> MovingPtr<'a, T, A> {943MovingPtr(self.0.cast::<T>(), PhantomData)944}945946/// Consumes the [`OwningPtr`] to drop the underlying data of type `T`.947///948/// # Safety949/// - `T` must be the erased pointee type for this [`OwningPtr`].950/// - If the type parameter `A` is [`Unaligned`] then this pointer must be be [properly aligned]951/// for the pointee type `T`.952///953/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment954#[inline]955pub unsafe fn drop_as<T>(self) {956let ptr = self.as_ptr().cast::<T>().debug_ensure_aligned();957// SAFETY: The caller ensure the pointee is of type `T` and uphold safety for `drop_in_place`.958unsafe {959ptr.drop_in_place();960}961}962963/// Gets the underlying pointer, erasing the associated lifetime.964///965/// If possible, it is strongly encouraged to use the other more type-safe functions966/// over this function.967#[inline]968pub fn as_ptr(&self) -> *mut u8 {969self.0.as_ptr()970}971972/// Gets an immutable pointer from this owned pointer.973#[inline]974pub fn as_ref(&self) -> Ptr<'_, A> {975// SAFETY: The `Owning` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees976unsafe { Ptr::new(self.0) }977}978979/// Gets a mutable pointer from this owned pointer.980#[inline]981pub fn as_mut(&mut self) -> PtrMut<'_, A> {982// SAFETY: The `Owning` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees983unsafe { PtrMut::new(self.0) }984}985}986987impl<'a> OwningPtr<'a, Unaligned> {988/// Consumes the [`OwningPtr`] to obtain ownership of the underlying data of type `T`.989///990/// # Safety991/// - `T` must be the erased pointee type for this [`OwningPtr`].992pub unsafe fn read_unaligned<T>(self) -> T {993let ptr = self.as_ptr().cast::<T>();994// SAFETY: The caller ensure the pointee is of type `T` and uphold safety for `read_unaligned`.995unsafe { ptr.read_unaligned() }996}997}998999/// Conceptually equivalent to `&'a [T]` but with length information cut out for performance reasons1000pub struct ThinSlicePtr<'a, T> {1001ptr: NonNull<T>,1002#[cfg(debug_assertions)]1003len: usize,1004_marker: PhantomData<&'a [T]>,1005}10061007impl<'a, T> ThinSlicePtr<'a, T> {1008#[inline]1009/// Indexes the slice without doing bounds checks1010///1011/// # Safety1012/// `index` must be in-bounds.1013pub unsafe fn get(self, index: usize) -> &'a T {1014#[cfg(debug_assertions)]1015debug_assert!(index < self.len);10161017let ptr = self.ptr.as_ptr();1018// SAFETY: `index` is in-bounds so the resulting pointer is valid to dereference.1019unsafe { &*ptr.add(index) }1020}1021}10221023impl<'a, T> Clone for ThinSlicePtr<'a, T> {1024fn clone(&self) -> Self {1025*self1026}1027}10281029impl<'a, T> Copy for ThinSlicePtr<'a, T> {}10301031impl<'a, T> From<&'a [T]> for ThinSlicePtr<'a, T> {1032#[inline]1033fn from(slice: &'a [T]) -> Self {1034let ptr = slice.as_ptr().cast_mut();1035Self {1036// SAFETY: a reference can never be null1037ptr: unsafe { NonNull::new_unchecked(ptr.debug_ensure_aligned()) },1038#[cfg(debug_assertions)]1039len: slice.len(),1040_marker: PhantomData,1041}1042}1043}10441045/// Creates a dangling pointer with specified alignment.1046/// See [`NonNull::dangling`].1047pub const fn dangling_with_align(align: NonZeroUsize) -> NonNull<u8> {1048debug_assert!(align.is_power_of_two(), "Alignment must be power of two.");1049// SAFETY: The pointer will not be null, since it was created1050// from the address of a `NonZero<usize>`.1051// TODO: use https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.with_addr once stabilized1052unsafe { NonNull::new_unchecked(ptr::null_mut::<u8>().wrapping_add(align.get())) }1053}10541055mod private {1056use core::cell::UnsafeCell;10571058pub trait SealedUnsafeCell {}1059impl<'a, T> SealedUnsafeCell for &'a UnsafeCell<T> {}1060}10611062/// Extension trait for helper methods on [`UnsafeCell`]1063pub trait UnsafeCellDeref<'a, T>: private::SealedUnsafeCell {1064/// # Safety1065/// - The returned value must be unique and not alias any mutable or immutable references to the contents of the [`UnsafeCell`].1066/// - At all times, you must avoid data races. If multiple threads have access to the same [`UnsafeCell`], then any writes must have a proper happens-before relation to all other accesses or use atomics ([`UnsafeCell`] docs for reference).1067unsafe fn deref_mut(self) -> &'a mut T;10681069/// # Safety1070/// - For the lifetime `'a` of the returned value you must not construct a mutable reference to the contents of the [`UnsafeCell`].1071/// - At all times, you must avoid data races. If multiple threads have access to the same [`UnsafeCell`], then any writes must have a proper happens-before relation to all other accesses or use atomics ([`UnsafeCell`] docs for reference).1072unsafe fn deref(self) -> &'a T;10731074/// Returns a copy of the contained value.1075///1076/// # Safety1077/// - The [`UnsafeCell`] must not currently have a mutable reference to its content.1078/// - At all times, you must avoid data races. If multiple threads have access to the same [`UnsafeCell`], then any writes must have a proper happens-before relation to all other accesses or use atomics ([`UnsafeCell`] docs for reference).1079unsafe fn read(self) -> T1080where1081T: Copy;1082}10831084impl<'a, T> UnsafeCellDeref<'a, T> for &'a UnsafeCell<T> {1085#[inline]1086unsafe fn deref_mut(self) -> &'a mut T {1087// SAFETY: The caller upholds the alias rules.1088unsafe { &mut *self.get() }1089}1090#[inline]1091unsafe fn deref(self) -> &'a T {1092// SAFETY: The caller upholds the alias rules.1093unsafe { &*self.get() }1094}10951096#[inline]1097unsafe fn read(self) -> T1098where1099T: Copy,1100{1101// SAFETY: The caller upholds the alias rules.1102unsafe { self.get().read() }1103}1104}11051106trait DebugEnsureAligned {1107fn debug_ensure_aligned(self) -> Self;1108}11091110// Disable this for miri runs as it already checks if pointer to reference1111// casts are properly aligned.1112#[cfg(all(debug_assertions, not(miri)))]1113impl<T: Sized> DebugEnsureAligned for *mut T {1114#[track_caller]1115fn debug_ensure_aligned(self) -> Self {1116let align = align_of::<T>();1117// Implementation shamelessly borrowed from the currently unstable1118// ptr.is_aligned_to.1119//1120// Replace once https://github.com/rust-lang/rust/issues/96284 is stable.1121assert_eq!(1122self as usize & (align - 1),11230,1124"pointer is not aligned. Address {:p} does not have alignment {} for type {}",1125self,1126align,1127core::any::type_name::<T>()1128);1129self1130}1131}11321133#[cfg(any(not(debug_assertions), miri))]1134impl<T: Sized> DebugEnsureAligned for *mut T {1135#[inline(always)]1136fn debug_ensure_aligned(self) -> Self {1137self1138}1139}11401141/// Deconstructs a [`MovingPtr`] into its individual fields.1142///1143/// This consumes the [`MovingPtr`] and hands out [`MovingPtr`] wrappers around1144/// pointers to each of its fields. The value will *not* be dropped.1145///1146/// The field move expressions will be executed in the order they're provided to the macro.1147/// In the example below, the call to [`assign_to`] for `field_a` will always run before the1148/// calls for `field_b` and `field_c`.1149///1150/// # Safety1151/// This macro generates unsafe code and must be set up correctly to avoid undefined behavior.1152/// - The provided type must match the type of the value pointed to by the [`MovingPtr`].1153/// - The type and name of the fields must match the type's definition. For tuples and tuple structs,1154/// this would be the tuple indices.1155///1156/// # Example1157///1158/// ```1159/// use core::mem::{offset_of, MaybeUninit};1160/// use bevy_ptr::MovingPtr;1161/// # use bevy_ptr::Unaligned;1162/// # struct FieldAType(usize);1163/// # struct FieldBType(usize);1164/// # struct FieldCType(usize);1165///1166/// pub struct Parent {1167/// pub field_a: FieldAType,1168/// pub field_b: FieldBType,1169/// pub field_c: FieldCType,1170/// }1171///1172/// let parent = Parent {1173/// field_a: FieldAType(11),1174/// field_b: FieldBType(22),1175/// field_c: FieldCType(33),1176/// };1177///1178/// let mut target_a = FieldAType(101);1179/// let mut target_b = FieldBType(102);1180/// let mut target_c = FieldCType(103);1181///1182/// MovingPtr::make(parent, |parent_ptr| unsafe {1183/// bevy_ptr::deconstruct_moving_ptr!(parent_ptr, Parent {1184/// // The field name and type must match the name used in the type definition.1185/// // Each one will be a `MovingPtr` of the supplied type1186/// field_a: FieldAType => { field_a.assign_to(&mut target_a) },1187/// field_b: FieldBType => { field_b.assign_to(&mut target_b) },1188/// field_c: FieldCType => { field_c.assign_to(&mut target_c) },1189/// });1190/// });1191///1192/// assert_eq!(target_a.0, 11);1193/// assert_eq!(target_b.0, 22);1194/// assert_eq!(target_c.0, 33);1195/// ```1196///1197/// [`assign_to`]: MovingPtr::assign_to1198#[macro_export]1199macro_rules! deconstruct_moving_ptr {1200($ptr:ident, $self_type:tt {$($field_name:tt: $field_type:tt => $field_block:block,)*}) => {1201$(let $field_name = $ptr.move_field::<$field_type>(core::mem::offset_of!($self_type, $field_name));)*1202// Each field block may panic! Ensure that `parent_ptr` cannot be dropped before1203// calling them!1204core::mem::forget($ptr);1205$($field_block)*1206};1207}120812091210