#![doc = include_str!("../README.md")]1#![no_std]2#![cfg_attr(docsrs, feature(doc_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},14ops::{Deref, DerefMut},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 {107ptr::drop_in_place(ptr);108}109}110}111112impl IsAligned for Unaligned {113#[inline]114unsafe fn read_ptr<T>(ptr: *const T) -> T {115// SAFETY:116// - The caller is required to ensure that `src` must be valid for reads.117// - The caller is required to ensure that `src` points to a valid instance of type `T`.118unsafe { ptr.read_unaligned() }119}120121#[inline]122unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {123// SAFETY:124// - The caller is required to ensure that `src` must be valid for reads.125// - The caller is required to ensure that `dst` must be valid for writes.126// - This is doing a byte-wise copy. `src` and `dst` are always guaranteed to be127// aligned.128// - The caller is required to ensure that the memory region covered by `src`129// and `dst`, fitting up to `count` elements do not overlap.130unsafe {131ptr::copy_nonoverlapping::<u8>(132src.cast::<u8>(),133dst.cast::<u8>(),134count * size_of::<T>(),135);136}137}138139#[inline]140unsafe fn drop_in_place<T>(ptr: *mut T) {141// SAFETY:142// - The caller is required to ensure that `ptr` must be valid for reads and writes.143// - The caller is required to ensure that `ptr` points to a valid instance of type `T`.144// - This type is not `Aligned` so the caller does not need to ensure that `ptr` is properly aligned for type `T`.145// - The caller is required to ensure that `ptr` points must be valid for dropping.146// - The caller is required to ensure that the value `ptr` points must not be used after this function147// call.148unsafe {149drop(ptr.read_unaligned());150}151}152}153154mod sealed {155pub trait Sealed {}156impl Sealed for super::Aligned {}157impl Sealed for super::Unaligned {}158}159160/// A newtype around [`NonNull`] that only allows conversion to read-only borrows or pointers.161///162/// This type can be thought of as the `*const T` to [`NonNull<T>`]'s `*mut T`.163#[derive(Clone, Copy)]164#[repr(transparent)]165pub struct ConstNonNull<T: ?Sized>(NonNull<T>);166167impl<T: ?Sized> ConstNonNull<T> {168/// Creates a new `ConstNonNull` if `ptr` is non-null.169///170/// # Examples171///172/// ```173/// use bevy_ptr::ConstNonNull;174///175/// let x = 0u32;176/// let ptr = ConstNonNull::<u32>::new(&x as *const _).expect("ptr is null!");177///178/// if let Some(ptr) = ConstNonNull::<u32>::new(core::ptr::null()) {179/// unreachable!();180/// }181/// ```182pub fn new(ptr: *const T) -> Option<Self> {183NonNull::new(ptr.cast_mut()).map(Self)184}185186/// Creates a new `ConstNonNull`.187///188/// # Safety189///190/// `ptr` must be non-null.191///192/// # Examples193///194/// ```195/// use bevy_ptr::ConstNonNull;196///197/// let x = 0u32;198/// let ptr = unsafe { ConstNonNull::new_unchecked(&x as *const _) };199/// ```200///201/// *Incorrect* usage of this function:202///203/// ```rust,no_run204/// use bevy_ptr::ConstNonNull;205///206/// // NEVER DO THAT!!! This is undefined behavior. ⚠️207/// let ptr = unsafe { ConstNonNull::<u32>::new_unchecked(core::ptr::null()) };208/// ```209pub const unsafe fn new_unchecked(ptr: *const T) -> Self {210// SAFETY: This function's safety invariants are identical to `NonNull::new_unchecked`211// The caller must satisfy all of them.212unsafe { Self(NonNull::new_unchecked(ptr.cast_mut())) }213}214215/// Returns a shared reference to the value.216///217/// # Safety218///219/// When calling this method, you have to ensure that all of the following is true:220///221/// * The pointer must be [properly aligned].222///223/// * It must be "dereferenceable" in the sense defined in [the module documentation].224///225/// * The pointer must point to an initialized instance of `T`.226///227/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is228/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.229/// In particular, while this reference exists, the memory the pointer points to must230/// not get mutated (except inside `UnsafeCell`).231///232/// This applies even if the result of this method is unused!233/// (The part about being initialized is not yet fully decided, but until234/// it is, the only safe approach is to ensure that they are indeed initialized.)235///236/// # Examples237///238/// ```239/// use bevy_ptr::ConstNonNull;240///241/// let mut x = 0u32;242/// let ptr = ConstNonNull::new(&mut x as *mut _).expect("ptr is null!");243///244/// let ref_x = unsafe { ptr.as_ref() };245/// println!("{ref_x}");246/// ```247///248/// [the module documentation]: core::ptr#safety249/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment250#[inline]251pub unsafe fn as_ref<'a>(&self) -> &'a T {252// SAFETY: This function's safety invariants are identical to `NonNull::as_ref`253// The caller must satisfy all of them.254unsafe { self.0.as_ref() }255}256}257258impl<T: ?Sized> From<NonNull<T>> for ConstNonNull<T> {259fn from(value: NonNull<T>) -> ConstNonNull<T> {260ConstNonNull(value)261}262}263264impl<'a, T: ?Sized> From<&'a T> for ConstNonNull<T> {265fn from(value: &'a T) -> ConstNonNull<T> {266ConstNonNull(NonNull::from(value))267}268}269270impl<'a, T: ?Sized> From<&'a mut T> for ConstNonNull<T> {271fn from(value: &'a mut T) -> ConstNonNull<T> {272ConstNonNull(NonNull::from(value))273}274}275276/// Type-erased borrow of some unknown type chosen when constructing this type.277///278/// This type tries to act "borrow-like" which means that:279/// - It should be considered immutable: its target must not be changed while this pointer is alive.280/// - It must always point to a valid value of whatever the pointee type is.281/// - The lifetime `'a` accurately represents how long the pointer is valid for.282/// - If `A` is [`Aligned`], the pointer must always be [properly aligned] for the unknown pointee type.283///284/// It may be helpful to think of this type as similar to `&'a dyn Any` but without285/// the metadata and able to point to data that does not correspond to a Rust type.286///287/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment288#[derive(Copy, Clone)]289#[repr(transparent)]290pub struct Ptr<'a, A: IsAligned = Aligned>(NonNull<u8>, PhantomData<(&'a u8, A)>);291292/// Type-erased mutable borrow of some unknown type chosen when constructing this type.293///294/// This type tries to act "borrow-like" which means that:295/// - Pointer is considered exclusive and mutable. It cannot be cloned as this would lead to296/// aliased mutability.297/// - It must always point to a valid value of whatever the pointee type is.298/// - The lifetime `'a` accurately represents how long the pointer is valid for.299/// - If `A` is [`Aligned`], the pointer must always be [properly aligned] for the unknown pointee type.300///301/// It may be helpful to think of this type as similar to `&'a mut dyn Any` but without302/// the metadata and able to point to data that does not correspond to a Rust type.303///304/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment305#[repr(transparent)]306pub struct PtrMut<'a, A: IsAligned = Aligned>(NonNull<u8>, PhantomData<(&'a mut u8, A)>);307308/// Type-erased [`Box`]-like pointer to some unknown type chosen when constructing this type.309///310/// Conceptually represents ownership of whatever data is being pointed to and so is311/// responsible for calling its `Drop` impl. This pointer is _not_ responsible for freeing312/// the memory pointed to by this pointer as it may be pointing to an element in a `Vec` or313/// to a local in a function etc.314///315/// This type tries to act "borrow-like" which means that:316/// - Pointer should be considered exclusive and mutable. It cannot be cloned as this would lead317/// to aliased mutability and potentially use after free bugs.318/// - It must always point to a valid value of whatever the pointee type is.319/// - The lifetime `'a` accurately represents how long the pointer is valid for.320/// - If `A` is [`Aligned`], the pointer must always be [properly aligned] for the unknown pointee type.321///322/// It may be helpful to think of this type as similar to `&'a mut ManuallyDrop<dyn Any>` but323/// without the metadata and able to point to data that does not correspond to a Rust type.324///325/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment326/// [`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html327#[repr(transparent)]328pub struct OwningPtr<'a, A: IsAligned = Aligned>(NonNull<u8>, PhantomData<(&'a mut u8, A)>);329330/// A [`Box`]-like pointer for moving a value to a new memory location without needing to pass by331/// value.332///333/// Conceptually represents ownership of whatever data is being pointed to and will call its334/// [`Drop`] impl upon being dropped. This pointer is _not_ responsible for freeing335/// the memory pointed to by this pointer as it may be pointing to an element in a `Vec` or336/// to a local in a function etc.337///338/// This type tries to act "borrow-like" which means that:339/// - Pointer should be considered exclusive and mutable. It cannot be cloned as this would lead340/// to aliased mutability and potentially use after free bugs.341/// - It must always point to a valid value of whatever the pointee type is.342/// - The lifetime `'a` accurately represents how long the pointer is valid for.343/// - It does not support pointer arithmetic in any way.344/// - If `A` is [`Aligned`], the pointer must always be [properly aligned] for the type `T`.345///346/// A value can be deconstructed into its fields via [`deconstruct_moving_ptr`], see it's documentation347/// for an example on how to use it.348///349/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment350/// [`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html351#[repr(transparent)]352pub struct MovingPtr<'a, T, A: IsAligned = Aligned>(NonNull<T>, PhantomData<(&'a mut T, A)>);353354macro_rules! impl_ptr {355($ptr:ident) => {356impl<'a> $ptr<'a, Aligned> {357/// Removes the alignment requirement of this pointer358pub fn to_unaligned(self) -> $ptr<'a, Unaligned> {359$ptr(self.0, PhantomData)360}361}362363impl<'a, A: IsAligned> From<$ptr<'a, A>> for NonNull<u8> {364fn from(ptr: $ptr<'a, A>) -> Self {365ptr.0366}367}368369impl<A: IsAligned> $ptr<'_, A> {370/// Calculates the offset from a pointer.371/// As the pointer is type-erased, there is no size information available. The provided372/// `count` parameter is in raw bytes.373///374/// *See also: [`ptr::offset`][ptr_offset]*375///376/// # Safety377/// - The offset cannot make the existing ptr null, or take it out of bounds for its allocation.378/// - If the `A` type parameter is [`Aligned`] then the offset must not make the resulting pointer379/// be unaligned for the pointee type.380/// - The value pointed by the resulting pointer must outlive the lifetime of this pointer.381///382/// [ptr_offset]: https://doc.rust-lang.org/std/primitive.pointer.html#method.offset383#[inline]384pub unsafe fn byte_offset(self, count: isize) -> Self {385Self(386// SAFETY: The caller upholds safety for `offset` and ensures the result is not null.387unsafe { NonNull::new_unchecked(self.as_ptr().offset(count)) },388PhantomData,389)390}391392/// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).393/// As the pointer is type-erased, there is no size information available. The provided394/// `count` parameter is in raw bytes.395///396/// *See also: [`ptr::add`][ptr_add]*397///398/// # Safety399/// - The offset cannot make the existing ptr null, or take it out of bounds for its allocation.400/// - If the `A` type parameter is [`Aligned`] then the offset must not make the resulting pointer401/// be unaligned for the pointee type.402/// - The value pointed by the resulting pointer must outlive the lifetime of this pointer.403///404/// [ptr_add]: https://doc.rust-lang.org/std/primitive.pointer.html#method.add405#[inline]406pub unsafe fn byte_add(self, count: usize) -> Self {407Self(408// SAFETY: The caller upholds safety for `add` and ensures the result is not null.409unsafe { NonNull::new_unchecked(self.as_ptr().add(count)) },410PhantomData,411)412}413}414415impl<A: IsAligned> Pointer for $ptr<'_, A> {416#[inline]417fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {418Pointer::fmt(&self.0, f)419}420}421422impl Debug for $ptr<'_, Aligned> {423#[inline]424fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {425write!(f, "{}<Aligned>({:?})", stringify!($ptr), self.0)426}427}428429impl Debug for $ptr<'_, Unaligned> {430#[inline]431fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {432write!(f, "{}<Unaligned>({:?})", stringify!($ptr), self.0)433}434}435};436}437438impl_ptr!(Ptr);439impl_ptr!(PtrMut);440impl_ptr!(OwningPtr);441442impl<'a, T> MovingPtr<'a, T, Aligned> {443/// Removes the alignment requirement of this pointer444#[inline]445pub fn to_unaligned(self) -> MovingPtr<'a, T, Unaligned> {446let value = MovingPtr(self.0, PhantomData);447mem::forget(self);448value449}450451/// Creates a [`MovingPtr`] from a provided value of type `T`.452///453/// For a safer alternative, it is strongly advised to use [`move_as_ptr`] where possible.454///455/// # Safety456/// - `value` must store a properly initialized value of type `T`.457/// - Once the returned [`MovingPtr`] has been used, `value` must be treated as458/// it were uninitialized unless it was explicitly leaked via [`core::mem::forget`].459#[inline]460pub unsafe fn from_value(value: &'a mut MaybeUninit<T>) -> Self {461// SAFETY:462// - MaybeUninit<T> has the same memory layout as T463// - The caller guarantees that `value` must point to a valid instance of type `T`.464MovingPtr(NonNull::from(value).cast::<T>(), PhantomData)465}466}467468impl<'a, T, A: IsAligned> MovingPtr<'a, T, A> {469/// Creates a new instance from a raw pointer.470///471/// For a safer alternative, it is strongly advised to use [`move_as_ptr`] where possible.472///473/// # Safety474/// - `inner` must point to valid value of `T`.475/// - If the `A` type parameter is [`Aligned`] then `inner` must be [properly aligned] for `T`.476/// - `inner` must have correct provenance to allow read and writes of the pointee type.477/// - The lifetime `'a` must be constrained such that this [`MovingPtr`] will stay valid and nothing478/// else can read or mutate the pointee while this [`MovingPtr`] is live.479///480/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment481#[inline]482pub unsafe fn new(inner: NonNull<T>) -> Self {483Self(inner, PhantomData)484}485486/// Partially moves out some fields inside of `self`.487///488/// The partially returned value is returned back pointing to [`MaybeUninit<T>`].489///490/// While calling this function is safe, care must be taken with the returned `MovingPtr` as it491/// points to a value that may no longer be completely valid.492///493/// # Example494///495/// ```496/// use core::mem::{offset_of, MaybeUninit, forget};497/// use bevy_ptr::{MovingPtr, move_as_ptr};498/// # struct FieldAType(usize);499/// # struct FieldBType(usize);500/// # struct FieldCType(usize);501/// # fn insert<T>(_ptr: MovingPtr<'_, T>) {}502///503/// struct Parent {504/// field_a: FieldAType,505/// field_b: FieldBType,506/// field_c: FieldCType,507/// }508///509/// # let parent = Parent {510/// # field_a: FieldAType(0),511/// # field_b: FieldBType(0),512/// # field_c: FieldCType(0),513/// # };514///515/// // Converts `parent` into a `MovingPtr`516/// move_as_ptr!(parent);517///518/// // SAFETY:519/// // - `field_a` and `field_b` are both unique.520/// let (partial_parent, ()) = MovingPtr::partial_move(parent, |parent_ptr| unsafe {521/// bevy_ptr::deconstruct_moving_ptr!({522/// let Parent { field_a, field_b, field_c } = parent_ptr;523/// });524///525/// insert(field_a);526/// insert(field_b);527/// forget(field_c);528/// });529///530/// // Move the rest of fields out of the parent.531/// // SAFETY:532/// // - `field_c` is by itself unique and does not conflict with the previous accesses533/// // inside `partial_move`.534/// unsafe {535/// bevy_ptr::deconstruct_moving_ptr!({536/// let MaybeUninit::<Parent> { field_a: _, field_b: _, field_c } = partial_parent;537/// });538///539/// insert(field_c);540/// }541/// ```542///543/// [`forget`]: core::mem::forget544#[inline]545pub fn partial_move<R>(546self,547f: impl FnOnce(MovingPtr<'_, T, A>) -> R,548) -> (MovingPtr<'a, MaybeUninit<T>, A>, R) {549let partial_ptr = self.0;550let ret = f(self);551(552MovingPtr(partial_ptr.cast::<MaybeUninit<T>>(), PhantomData),553ret,554)555}556557/// Reads the value pointed to by this pointer.558#[inline]559pub fn read(self) -> T {560// SAFETY:561// - `self.0` must be valid for reads as this type owns the value it points to.562// - `self.0` must always point to a valid instance of type `T`563// - If `A` is [`Aligned`], then `ptr` must be properly aligned for type `T`.564let value = unsafe { A::read_ptr(self.0.as_ptr()) };565mem::forget(self);566value567}568569/// Writes the value pointed to by this pointer to a provided location.570///571/// This does *not* drop the value stored at `dst` and it's the caller's responsibility572/// to ensure that it's properly dropped.573///574/// # Safety575/// - `dst` must be valid for writes.576/// - If the `A` type parameter is [`Aligned`] then `dst` must be [properly aligned] for `T`.577///578/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment579#[inline]580pub unsafe fn write_to(self, dst: *mut T) {581let src = self.0.as_ptr();582mem::forget(self);583// SAFETY:584// - `src` must be valid for reads as this pointer is considered to own the value it points to.585// - The caller is required to ensure that `dst` must be valid for writes.586// - As `A` is `Aligned`, the caller is required to ensure that `dst` is aligned and `src` must587// be aligned by the type's invariants.588unsafe { A::copy_nonoverlapping(src, dst, 1) };589}590591/// Writes the value pointed to by this pointer into `dst`.592///593/// The value previously stored at `dst` will be dropped.594#[inline]595pub fn assign_to(self, dst: &mut T) {596// SAFETY:597// - `dst` is a mutable borrow, it must point to a valid instance of `T`.598// - `dst` is a mutable borrow, it must point to value that is valid for dropping.599// - `dst` is a mutable borrow, it must not alias any other access.600unsafe {601ptr::drop_in_place(dst);602}603// SAFETY:604// - `dst` is a mutable borrow, it must be valid for writes.605// - `dst` is a mutable borrow, it must always be aligned.606unsafe {607self.write_to(dst);608}609}610611/// Creates a [`MovingPtr`] for a specific field within `self`.612///613/// This function is explicitly made for deconstructive moves.614///615/// The correct `byte_offset` for a field can be obtained via [`core::mem::offset_of`].616///617/// # Safety618/// - `f` must return a non-null pointer to a valid field inside `T`619/// - If `A` is [`Aligned`], then `T` must not be `repr(packed)`620/// - `self` should not be accessed or dropped as if it were a complete value after this function returns.621/// Other fields that have not been moved out of may still be accessed or dropped separately.622/// - This function cannot alias the field with any other access, including other calls to [`move_field`]623/// for the same field, without first calling [`forget`] on it first.624///625/// A result of the above invariants means that any operation that could cause `self` to be dropped while626/// the pointers to the fields are held will result in undefined behavior. This requires extra caution627/// around code that may panic. See the example below for an example of how to safely use this function.628///629/// # Example630///631/// ```632/// use core::mem::offset_of;633/// use bevy_ptr::{MovingPtr, move_as_ptr};634/// # struct FieldAType(usize);635/// # struct FieldBType(usize);636/// # struct FieldCType(usize);637/// # fn insert<T>(_ptr: MovingPtr<'_, T>) {}638///639/// struct Parent {640/// field_a: FieldAType,641/// field_b: FieldBType,642/// field_c: FieldCType,643/// }644///645/// let parent = Parent {646/// field_a: FieldAType(0),647/// field_b: FieldBType(0),648/// field_c: FieldCType(0),649/// };650///651/// // Converts `parent` into a `MovingPtr`.652/// move_as_ptr!(parent);653///654/// unsafe {655/// let field_a = parent.move_field(|ptr| &raw mut (*ptr).field_a);656/// let field_b = parent.move_field(|ptr| &raw mut (*ptr).field_b);657/// let field_c = parent.move_field(|ptr| &raw mut (*ptr).field_c);658/// // Each call to insert may panic! Ensure that `parent_ptr` cannot be dropped before659/// // calling them!660/// core::mem::forget(parent);661/// insert(field_a);662/// insert(field_b);663/// insert(field_c);664/// }665/// ```666///667/// [`forget`]: core::mem::forget668/// [`move_field`]: Self::move_field669#[inline(always)]670pub unsafe fn move_field<U>(&self, f: impl Fn(*mut T) -> *mut U) -> MovingPtr<'a, U, A> {671MovingPtr(672// SAFETY: The caller must ensure that `U` is the correct type for the field at `byte_offset`.673unsafe { NonNull::new_unchecked(f(self.0.as_ptr())) },674PhantomData,675)676}677}678679impl<'a, T, A: IsAligned> MovingPtr<'a, MaybeUninit<T>, A> {680/// Creates a [`MovingPtr`] for a specific field within `self`.681///682/// This function is explicitly made for deconstructive moves.683///684/// The correct `byte_offset` for a field can be obtained via [`core::mem::offset_of`].685///686/// # Safety687/// - `f` must return a non-null pointer to a valid field inside `T`688/// - If `A` is [`Aligned`], then `T` must not be `repr(packed)`689/// - `self` should not be accessed or dropped as if it were a complete value after this function returns.690/// Other fields that have not been moved out of may still be accessed or dropped separately.691/// - This function cannot alias the field with any other access, including other calls to [`move_field`]692/// for the same field, without first calling [`forget`] on it first.693///694/// [`forget`]: core::mem::forget695/// [`move_field`]: Self::move_field696#[inline(always)]697pub unsafe fn move_maybe_uninit_field<U>(698&self,699f: impl Fn(*mut T) -> *mut U,700) -> MovingPtr<'a, MaybeUninit<U>, A> {701let self_ptr = self.0.as_ptr().cast::<T>();702// SAFETY:703// - The caller must ensure that `U` is the correct type for the field at `byte_offset` and thus704// cannot be null.705// - `MaybeUninit<T>` is `repr(transparent)` and thus must have the same memory layout as `T``706let field_ptr = unsafe { NonNull::new_unchecked(f(self_ptr)) };707MovingPtr(field_ptr.cast::<MaybeUninit<U>>(), PhantomData)708}709}710711impl<'a, T, A: IsAligned> MovingPtr<'a, MaybeUninit<T>, A> {712/// Creates a [`MovingPtr`] pointing to a valid instance of `T`.713///714/// See also: [`MaybeUninit::assume_init`].715///716/// # Safety717/// It's up to the caller to ensure that the value pointed to by `self`718/// is really in an initialized state. Calling this when the content is not yet719/// fully initialized causes immediate undefined behavior.720#[inline]721pub unsafe fn assume_init(self) -> MovingPtr<'a, T, A> {722let value = MovingPtr(self.0.cast::<T>(), PhantomData);723mem::forget(self);724value725}726}727728impl<T, A: IsAligned> Pointer for MovingPtr<'_, T, A> {729#[inline]730fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {731Pointer::fmt(&self.0, f)732}733}734735impl<T> Debug for MovingPtr<'_, T, Aligned> {736#[inline]737fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {738write!(f, "MovingPtr<Aligned>({:?})", self.0)739}740}741742impl<T> Debug for MovingPtr<'_, T, Unaligned> {743#[inline]744fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {745write!(f, "MovingPtr<Unaligned>({:?})", self.0)746}747}748749impl<'a, T, A: IsAligned> From<MovingPtr<'a, T, A>> for OwningPtr<'a, A> {750#[inline]751fn from(value: MovingPtr<'a, T, A>) -> Self {752// SAFETY:753// - `value.0` must always point to valid value of type `T`.754// - The type parameter `A` is mirrored from input to output, keeping the same alignment guarantees.755// - `value.0` by construction must have correct provenance to allow read and writes of type `T`.756// - The lifetime `'a` is mirrored from input to output, keeping the same lifetime guarantees.757// - `OwningPtr` maintains the same aliasing invariants as `MovingPtr`.758let ptr = unsafe { OwningPtr::new(value.0.cast::<u8>()) };759mem::forget(value);760ptr761}762}763764impl<'a, T> TryFrom<MovingPtr<'a, T, Unaligned>> for MovingPtr<'a, T, Aligned> {765type Error = MovingPtr<'a, T, Unaligned>;766#[inline]767fn try_from(value: MovingPtr<'a, T, Unaligned>) -> Result<Self, Self::Error> {768let ptr = value.0;769if ptr.as_ptr().is_aligned() {770mem::forget(value);771Ok(MovingPtr(ptr, PhantomData))772} else {773Err(value)774}775}776}777778impl<T> Deref for MovingPtr<'_, T, Aligned> {779type Target = T;780#[inline]781fn deref(&self) -> &Self::Target {782let ptr = self.0.as_ptr().debug_ensure_aligned();783// SAFETY: This type owns the value it points to and the generic type parameter is `A` so this pointer must be aligned.784unsafe { &*ptr }785}786}787788impl<T> DerefMut for MovingPtr<'_, T, Aligned> {789#[inline]790fn deref_mut(&mut self) -> &mut Self::Target {791let ptr = self.0.as_ptr().debug_ensure_aligned();792// SAFETY: This type owns the value it points to and the generic type parameter is `A` so this pointer must be aligned.793unsafe { &mut *ptr }794}795}796797impl<T, A: IsAligned> Drop for MovingPtr<'_, T, A> {798fn drop(&mut self) {799// SAFETY:800// - `self.0` must be valid for reads and writes as this pointer type owns the value it points to.801// - `self.0` must always point to a valid instance of type `T`802// - If `A` is `Aligned`, then `ptr` must be properly aligned for type `T` by construction.803// - `self.0` owns the value it points to so it must always be valid for dropping until this pointer is dropped.804// - This type owns the value it points to, so it's required to not mutably alias value that it points to.805unsafe { A::drop_in_place(self.0.as_ptr()) };806}807}808809impl<'a, A: IsAligned> Ptr<'a, A> {810/// Creates a new instance from a raw pointer.811///812/// # Safety813/// - `inner` must point to valid value of whatever the pointee type is.814/// - If the `A` type parameter is [`Aligned`] then `inner` must be [properly aligned] for the pointee type.815/// - `inner` must have correct provenance to allow reads of the pointee type.816/// - The lifetime `'a` must be constrained such that this [`Ptr`] will stay valid and nothing817/// can mutate the pointee while this [`Ptr`] is live except through an [`UnsafeCell`].818///819/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment820#[inline]821pub unsafe fn new(inner: NonNull<u8>) -> Self {822Self(inner, PhantomData)823}824825/// Transforms this [`Ptr`] into an [`PtrMut`]826///827/// # Safety828/// * The data pointed to by this `Ptr` must be valid for writes.829/// * There must be no active references (mutable or otherwise) to the data underlying this `Ptr`.830/// * Another [`PtrMut`] for the same [`Ptr`] must not be created until the first is dropped.831#[inline]832pub unsafe fn assert_unique(self) -> PtrMut<'a, A> {833PtrMut(self.0, PhantomData)834}835836/// Transforms this [`Ptr<T>`] into a `&T` with the same lifetime837///838/// # Safety839/// - `T` must be the erased pointee type for this [`Ptr`].840/// - If the type parameter `A` is [`Unaligned`] then this pointer must 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<T>(self) -> &'a 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 { &*ptr }849}850851/// Gets the underlying pointer, erasing the associated lifetime.852///853/// If possible, it is strongly encouraged to use [`deref`](Self::deref) over this function,854/// as it retains the lifetime.855#[inline]856pub fn as_ptr(self) -> *mut u8 {857self.0.as_ptr()858}859}860861impl<'a, T: ?Sized> From<&'a T> for Ptr<'a> {862#[inline]863fn from(val: &'a T) -> Self {864// SAFETY: The returned pointer has the same lifetime as the passed reference.865// Access is immutable.866unsafe { Self::new(NonNull::from(val).cast()) }867}868}869870impl<'a, A: IsAligned> PtrMut<'a, A> {871/// Creates a new instance from a raw pointer.872///873/// # Safety874/// - `inner` must point to valid value of whatever the pointee type is.875/// - If the `A` type parameter is [`Aligned`] then `inner` must be [properly aligned] for the pointee type.876/// - `inner` must have correct provenance to allow read and writes of the pointee type.877/// - The lifetime `'a` must be constrained such that this [`PtrMut`] will stay valid and nothing878/// else can read or mutate the pointee while this [`PtrMut`] is live.879///880/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment881#[inline]882pub unsafe fn new(inner: NonNull<u8>) -> Self {883Self(inner, PhantomData)884}885886/// Transforms this [`PtrMut`] into an [`OwningPtr`]887///888/// # Safety889/// Must have right to drop or move out of [`PtrMut`].890#[inline]891pub unsafe fn promote(self) -> OwningPtr<'a, A> {892OwningPtr(self.0, PhantomData)893}894895/// Transforms this [`PtrMut<T>`] into a `&mut T` with the same lifetime896///897/// # Safety898/// - `T` must be the erased pointee type for this [`PtrMut`].899/// - If the type parameter `A` is [`Unaligned`] then this pointer must be [properly aligned]900/// for the pointee type `T`.901///902/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment903#[inline]904pub unsafe fn deref_mut<T>(self) -> &'a mut T {905let ptr = self.as_ptr().cast::<T>().debug_ensure_aligned();906// SAFETY: The caller ensures the pointee is of type `T` and the pointer can be dereferenced.907unsafe { &mut *ptr }908}909910/// Gets the underlying pointer, erasing the associated lifetime.911///912/// If possible, it is strongly encouraged to use [`deref_mut`](Self::deref_mut) over913/// this function, as it retains the lifetime.914#[inline]915pub fn as_ptr(&self) -> *mut u8 {916self.0.as_ptr()917}918919/// Gets a [`PtrMut`] from this with a smaller lifetime.920#[inline]921pub fn reborrow(&mut self) -> PtrMut<'_, A> {922// SAFETY: the ptrmut we're borrowing from is assumed to be valid923unsafe { PtrMut::new(self.0) }924}925926/// Gets an immutable reference from this mutable reference927#[inline]928pub fn as_ref(&self) -> Ptr<'_, A> {929// SAFETY: The `PtrMut` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees930unsafe { Ptr::new(self.0) }931}932}933934impl<'a, T: ?Sized> From<&'a mut T> for PtrMut<'a> {935#[inline]936fn from(val: &'a mut T) -> Self {937// SAFETY: The returned pointer has the same lifetime as the passed reference.938// The reference is mutable, and thus will not alias.939unsafe { Self::new(NonNull::from(val).cast()) }940}941}942943impl<'a> OwningPtr<'a> {944/// This exists mostly to reduce compile times;945/// code is only duplicated per type, rather than per function called.946///947/// # Safety948///949/// Safety constraints of [`PtrMut::promote`] must be upheld.950unsafe fn make_internal<T>(temp: &mut ManuallyDrop<T>) -> OwningPtr<'_> {951// SAFETY: The constraints of `promote` are upheld by caller.952unsafe { PtrMut::from(&mut *temp).promote() }953}954955/// Consumes a value and creates an [`OwningPtr`] to it while ensuring a double drop does not happen.956#[inline]957pub fn make<T, F: FnOnce(OwningPtr<'_>) -> R, R>(val: T, f: F) -> R {958let mut val = ManuallyDrop::new(val);959// SAFETY: The value behind the pointer will not get dropped or observed later,960// so it's safe to promote it to an owning pointer.961f(unsafe { Self::make_internal(&mut val) })962}963}964965impl<'a, A: IsAligned> OwningPtr<'a, A> {966/// Creates a new instance from a raw pointer.967///968/// # Safety969/// - `inner` must point to valid value of whatever the pointee type is.970/// - If the `A` type parameter is [`Aligned`] then `inner` must be [properly aligned] for the pointee type.971/// - `inner` must have correct provenance to allow read and writes of the pointee type.972/// - The lifetime `'a` must be constrained such that this [`OwningPtr`] will stay valid and nothing973/// else can read or mutate the pointee while this [`OwningPtr`] is live.974///975/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment976#[inline]977pub unsafe fn new(inner: NonNull<u8>) -> Self {978Self(inner, PhantomData)979}980981/// Consumes the [`OwningPtr`] to obtain ownership of the underlying data of type `T`.982///983/// # Safety984/// - `T` must be the erased pointee type for this [`OwningPtr`].985/// - If the type parameter `A` is [`Unaligned`] then this pointer must be [properly aligned]986/// for the pointee type `T`.987///988/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment989#[inline]990pub unsafe fn read<T>(self) -> T {991let ptr = self.as_ptr().cast::<T>().debug_ensure_aligned();992// SAFETY: The caller ensure the pointee is of type `T` and uphold safety for `read`.993unsafe { ptr.read() }994}995996/// Casts to a concrete type as a [`MovingPtr`].997///998/// # Safety999/// - `T` must be the erased pointee type for this [`OwningPtr`].1000#[inline]1001pub unsafe fn cast<T>(self) -> MovingPtr<'a, T, A> {1002MovingPtr(self.0.cast::<T>(), PhantomData)1003}10041005/// Consumes the [`OwningPtr`] to drop the underlying data of type `T`.1006///1007/// # Safety1008/// - `T` must be the erased pointee type for this [`OwningPtr`].1009/// - If the type parameter `A` is [`Unaligned`] then this pointer must be [properly aligned]1010/// for the pointee type `T`.1011///1012/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment1013#[inline]1014pub unsafe fn drop_as<T>(self) {1015let ptr = self.as_ptr().cast::<T>().debug_ensure_aligned();1016// SAFETY: The caller ensure the pointee is of type `T` and uphold safety for `drop_in_place`.1017unsafe {1018ptr.drop_in_place();1019}1020}10211022/// Gets the underlying pointer, erasing the associated lifetime.1023///1024/// If possible, it is strongly encouraged to use the other more type-safe functions1025/// over this function.1026#[inline]1027pub fn as_ptr(&self) -> *mut u8 {1028self.0.as_ptr()1029}10301031/// Gets an immutable pointer from this owned pointer.1032#[inline]1033pub fn as_ref(&self) -> Ptr<'_, A> {1034// SAFETY: The `Owning` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees1035unsafe { Ptr::new(self.0) }1036}10371038/// Gets a mutable pointer from this owned pointer.1039#[inline]1040pub fn as_mut(&mut self) -> PtrMut<'_, A> {1041// SAFETY: The `Owning` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees1042unsafe { PtrMut::new(self.0) }1043}1044}10451046impl<'a> OwningPtr<'a, Unaligned> {1047/// Consumes the [`OwningPtr`] to obtain ownership of the underlying data of type `T`.1048///1049/// # Safety1050/// - `T` must be the erased pointee type for this [`OwningPtr`].1051pub unsafe fn read_unaligned<T>(self) -> T {1052let ptr = self.as_ptr().cast::<T>();1053// SAFETY: The caller ensure the pointee is of type `T` and uphold safety for `read_unaligned`.1054unsafe { ptr.read_unaligned() }1055}1056}10571058/// Conceptually equivalent to `&'a [T]` but with length information cut out for performance1059/// reasons.1060///1061/// Because this type does not store the length of the slice, it is unable to do any sort of bounds1062/// checking. As such, only [`Self::get_unchecked()`] is available for indexing into the slice,1063/// where the user is responsible for checking the bounds.1064///1065/// When compiled in debug mode (`#[cfg(debug_assertion)]`), this type will store the length of the1066/// slice and perform bounds checking in [`Self::get_unchecked()`].1067///1068/// # Example1069///1070/// ```1071/// # use core::mem::size_of;1072/// # use bevy_ptr::ThinSlicePtr;1073/// #1074/// let slice: &[u32] = &[2, 4, 8];1075/// let thin_slice = ThinSlicePtr::from(slice);1076///1077/// assert_eq!(*unsafe { thin_slice.get_unchecked(0) }, 2);1078/// assert_eq!(*unsafe { thin_slice.get_unchecked(1) }, 4);1079/// assert_eq!(*unsafe { thin_slice.get_unchecked(2) }, 8);1080/// ```1081pub struct ThinSlicePtr<'a, T> {1082ptr: NonNull<T>,1083#[cfg(debug_assertions)]1084len: usize,1085_marker: PhantomData<&'a [T]>,1086}10871088impl<'a, T> ThinSlicePtr<'a, T> {1089/// Indexes the slice without performing bounds checks.1090///1091/// # Safety1092///1093/// `index` must be in-bounds.1094#[inline]1095pub unsafe fn get_unchecked(&self, index: usize) -> &'a T {1096// We cannot use `debug_assert!` here because `self.len` does not exist when not in debug1097// mode.1098#[cfg(debug_assertions)]1099assert!(index < self.len, "tried to index out-of-bounds of a slice");11001101// SAFETY: The caller guarantees `index` is in-bounds so that the resulting pointer is1102// valid to dereference.1103unsafe { &*self.ptr.add(index).as_ptr() }1104}11051106/// Returns a slice without performing bounds checks.1107///1108/// # Safety1109///1110/// - There must be no mutable aliases for the lifetime `'a` to the slice. to the slice.1111/// - `len` must be less than or equal to the length of the slice.1112pub unsafe fn as_slice_unchecked(&self, len: usize) -> &'a [T] {1113#[cfg(debug_assertions)]1114assert!(len <= self.len, "tried to create an out-of-bounds slice");11151116// SAFETY:1117// - The caller guarantees `len` is not greater than the length of the slice.1118// - The caller guarantees the aliasing rules.1119// - `self.ptr` is a valid pointer for the type `T`.1120// - `len` is valid hence `len * size_of::<T>()` is less than `isize::MAX`.1121unsafe { core::slice::from_raw_parts(self.ptr.as_ptr(), len) }1122}11231124/// Indexes the slice without performing bounds checks.1125///1126/// # Safety1127///1128/// `index` must be in-bounds.1129#[deprecated(since = "0.18.0", note = "use get_unchecked() instead")]1130pub unsafe fn get(self, index: usize) -> &'a T {1131// SAFETY: The caller guarantees that `index` is in-bounds.1132unsafe { self.get_unchecked(index) }1133}1134}11351136impl<'a, T> ThinSlicePtr<'a, UnsafeCell<T>> {1137/// Returns a mutable reference of the slice1138///1139/// # Safety1140///1141/// - There must not be any aliases for the lifetime `'a` to the slice.1142/// - `len` must be less than or equal to the length of the slice.1143pub unsafe fn as_mut_slice_unchecked(&self, len: usize) -> &'a mut [T] {1144#[cfg(debug_assertions)]1145assert!(len <= self.len, "tried to create an out-of-bounds slice");11461147// SAFETY:1148// - The caller ensures no aliases exist and `len` is in-bounds.1149// - `self.ptr` is a valid pointer for the type `T`.1150// - `len` is valid hence `len * size_of::<T>()` is less than `isize::MAX`.1151unsafe { core::slice::from_raw_parts_mut(UnsafeCell::raw_get(self.ptr.as_ptr()), len) }1152}11531154/// Returns a slice pointer to the underlying type `T`.1155pub fn cast(&self) -> ThinSlicePtr<'a, T> {1156ThinSlicePtr {1157// SAFETY: `self.ptr` is non null hence `UnsafeCell::raw_get` always returns a non null pointer1158ptr: unsafe { NonNull::new_unchecked(UnsafeCell::raw_get(self.ptr.as_ptr())) },1159#[cfg(debug_assertions)]1160len: self.len,1161_marker: PhantomData,1162}1163}1164}11651166impl<'a, T> Clone for ThinSlicePtr<'a, T> {1167fn clone(&self) -> Self {1168*self1169}1170}11711172impl<'a, T> Copy for ThinSlicePtr<'a, T> {}11731174impl<'a, T> From<&'a [T]> for ThinSlicePtr<'a, T> {1175#[inline]1176fn from(slice: &'a [T]) -> Self {1177let ptr = slice.as_ptr().cast_mut().debug_ensure_aligned();11781179Self {1180// SAFETY: A reference can never be null.1181ptr: unsafe { NonNull::new_unchecked(ptr) },1182#[cfg(debug_assertions)]1183len: slice.len(),1184_marker: PhantomData,1185}1186}1187}11881189mod private {1190use core::cell::UnsafeCell;11911192pub trait SealedUnsafeCell {}1193impl<'a, T> SealedUnsafeCell for &'a UnsafeCell<T> {}1194}11951196/// Extension trait for helper methods on [`UnsafeCell`]1197pub trait UnsafeCellDeref<'a, T>: private::SealedUnsafeCell {1198/// # Safety1199/// - The returned value must be unique and not alias any mutable or immutable references to the contents of the [`UnsafeCell`].1200/// - 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).1201unsafe fn deref_mut(self) -> &'a mut T;12021203/// # Safety1204/// - For the lifetime `'a` of the returned value you must not construct a mutable reference to the contents of the [`UnsafeCell`].1205/// - 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).1206unsafe fn deref(self) -> &'a T;12071208/// Returns a copy of the contained value.1209///1210/// # Safety1211/// - The [`UnsafeCell`] must not currently have a mutable reference to its content.1212/// - 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).1213unsafe fn read(self) -> T1214where1215T: Copy;1216}12171218impl<'a, T> UnsafeCellDeref<'a, T> for &'a UnsafeCell<T> {1219#[inline]1220unsafe fn deref_mut(self) -> &'a mut T {1221// SAFETY: The caller upholds the alias rules.1222unsafe { &mut *self.get() }1223}1224#[inline]1225unsafe fn deref(self) -> &'a T {1226// SAFETY: The caller upholds the alias rules.1227unsafe { &*self.get() }1228}12291230#[inline]1231unsafe fn read(self) -> T1232where1233T: Copy,1234{1235// SAFETY: The caller upholds the alias rules.1236unsafe { self.get().read() }1237}1238}12391240trait DebugEnsureAligned {1241fn debug_ensure_aligned(self) -> Self;1242}12431244// Disable this for miri runs as it already checks if pointer to reference1245// casts are properly aligned.1246#[cfg(all(debug_assertions, not(miri)))]1247impl<T: Sized> DebugEnsureAligned for *mut T {1248#[track_caller]1249fn debug_ensure_aligned(self) -> Self {1250assert!(1251self.is_aligned(),1252"pointer is not aligned. Address {:p} does not have alignment {} for type {}",1253self,1254align_of::<T>(),1255core::any::type_name::<T>()1256);1257self1258}1259}12601261#[cfg(any(not(debug_assertions), miri))]1262impl<T: Sized> DebugEnsureAligned for *mut T {1263#[inline(always)]1264fn debug_ensure_aligned(self) -> Self {1265self1266}1267}12681269/// Safely converts a owned value into a [`MovingPtr`] while minimizing the number of stack copies.1270///1271/// This cannot be used as expression and must be used as a statement. Internally this macro works via variable shadowing.1272#[macro_export]1273macro_rules! move_as_ptr {1274($value: ident) => {1275let mut $value = core::mem::MaybeUninit::new($value);1276// SAFETY:1277// - This macro shadows a MaybeUninit value that took ownership of the original value.1278// it is impossible to refer to the original value, preventing further access after1279// the `MovingPtr` has been used. `MaybeUninit` also prevents the compiler from1280// dropping the original value.1281let $value = unsafe { $crate::MovingPtr::from_value(&mut $value) };1282};1283}12841285/// Helper macro used by [`deconstruct_moving_ptr`] to extract1286/// the pattern from `field: pattern` or `field` shorthand.1287#[macro_export]1288#[doc(hidden)]1289macro_rules! get_pattern {1290($field_index:tt) => {1291$field_index1292};1293($field_index:tt: $pattern:pat) => {1294$pattern1295};1296}12971298/// Deconstructs a [`MovingPtr`] into its individual fields.1299///1300/// This consumes the [`MovingPtr`] and hands out [`MovingPtr`] wrappers around1301/// pointers to each of its fields. The value will *not* be dropped.1302///1303/// The macro should wrap a `let` expression with a struct pattern.1304/// It does not support matching tuples by position,1305/// so for tuple structs you should use `0: pat` syntax.1306///1307/// For tuples themselves, pass the identifier `tuple` instead of the struct name,1308/// like `let tuple { 0: pat0, 1: pat1 } = value`.1309///1310/// This can also project into `MaybeUninit`.1311/// Wrap the type name or `tuple` with `MaybeUninit::<_>`,1312/// and the macro will deconstruct a `MovingPtr<MaybeUninit<ParentType>>`1313/// into `MovingPtr<MaybeUninit<FieldType>>` values.1314///1315/// # Examples1316///1317/// ## Structs1318///1319/// ```1320/// use core::mem::{offset_of, MaybeUninit};1321/// use bevy_ptr::{MovingPtr, move_as_ptr};1322/// # use bevy_ptr::Unaligned;1323/// # struct FieldAType(usize);1324/// # struct FieldBType(usize);1325/// # struct FieldCType(usize);1326///1327/// # pub struct Parent {1328/// # pub field_a: FieldAType,1329/// # pub field_b: FieldBType,1330/// # pub field_c: FieldCType,1331/// # }1332///1333/// let parent = Parent {1334/// field_a: FieldAType(11),1335/// field_b: FieldBType(22),1336/// field_c: FieldCType(33),1337/// };1338///1339/// let mut target_a = FieldAType(101);1340/// let mut target_b = FieldBType(102);1341/// let mut target_c = FieldCType(103);1342///1343/// // Converts `parent` into a `MovingPtr`1344/// move_as_ptr!(parent);1345///1346/// // The field names must match the name used in the type definition.1347/// // Each one will be a `MovingPtr` of the field's type.1348/// bevy_ptr::deconstruct_moving_ptr!({1349/// let Parent { field_a, field_b, field_c } = parent;1350/// });1351///1352/// field_a.assign_to(&mut target_a);1353/// field_b.assign_to(&mut target_b);1354/// field_c.assign_to(&mut target_c);1355///1356/// assert_eq!(target_a.0, 11);1357/// assert_eq!(target_b.0, 22);1358/// assert_eq!(target_c.0, 33);1359/// ```1360///1361/// ## Tuples1362///1363/// ```1364/// use core::mem::{offset_of, MaybeUninit};1365/// use bevy_ptr::{MovingPtr, move_as_ptr};1366/// # use bevy_ptr::Unaligned;1367/// # struct FieldAType(usize);1368/// # struct FieldBType(usize);1369/// # struct FieldCType(usize);1370///1371/// # pub struct Parent {1372/// # pub field_a: FieldAType,1373/// # pub field_b: FieldBType,1374/// # pub field_c: FieldCType,1375/// # }1376///1377/// let parent = (1378/// FieldAType(11),1379/// FieldBType(22),1380/// FieldCType(33),1381/// );1382///1383/// let mut target_a = FieldAType(101);1384/// let mut target_b = FieldBType(102);1385/// let mut target_c = FieldCType(103);1386///1387/// // Converts `parent` into a `MovingPtr`1388/// move_as_ptr!(parent);1389///1390/// // The field names must match the name used in the type definition.1391/// // Each one will be a `MovingPtr` of the field's type.1392/// bevy_ptr::deconstruct_moving_ptr!({1393/// let tuple { 0: field_a, 1: field_b, 2: field_c } = parent;1394/// });1395///1396/// field_a.assign_to(&mut target_a);1397/// field_b.assign_to(&mut target_b);1398/// field_c.assign_to(&mut target_c);1399///1400/// assert_eq!(target_a.0, 11);1401/// assert_eq!(target_b.0, 22);1402/// assert_eq!(target_c.0, 33);1403/// ```1404///1405/// ## `MaybeUninit`1406///1407/// ```1408/// use core::mem::{offset_of, MaybeUninit};1409/// use bevy_ptr::{MovingPtr, move_as_ptr};1410/// # use bevy_ptr::Unaligned;1411/// # struct FieldAType(usize);1412/// # struct FieldBType(usize);1413/// # struct FieldCType(usize);1414///1415/// # pub struct Parent {1416/// # pub field_a: FieldAType,1417/// # pub field_b: FieldBType,1418/// # pub field_c: FieldCType,1419/// # }1420///1421/// let parent = MaybeUninit::new(Parent {1422/// field_a: FieldAType(11),1423/// field_b: FieldBType(22),1424/// field_c: FieldCType(33),1425/// });1426///1427/// let mut target_a = MaybeUninit::new(FieldAType(101));1428/// let mut target_b = MaybeUninit::new(FieldBType(102));1429/// let mut target_c = MaybeUninit::new(FieldCType(103));1430///1431/// // Converts `parent` into a `MovingPtr`1432/// move_as_ptr!(parent);1433///1434/// // The field names must match the name used in the type definition.1435/// // Each one will be a `MovingPtr` of the field's type.1436/// bevy_ptr::deconstruct_moving_ptr!({1437/// let MaybeUninit::<Parent> { field_a, field_b, field_c } = parent;1438/// });1439///1440/// field_a.assign_to(&mut target_a);1441/// field_b.assign_to(&mut target_b);1442/// field_c.assign_to(&mut target_c);1443///1444/// unsafe {1445/// assert_eq!(target_a.assume_init().0, 11);1446/// assert_eq!(target_b.assume_init().0, 22);1447/// assert_eq!(target_c.assume_init().0, 33);1448/// }1449/// ```1450///1451/// [`assign_to`]: MovingPtr::assign_to1452#[macro_export]1453macro_rules! deconstruct_moving_ptr {1454({ let tuple { $($field_index:tt: $pattern:pat),* $(,)? } = $ptr:expr ;}) => {1455// Specify the type to make sure the `mem::forget` doesn't forget a mere `&mut MovingPtr`1456let mut ptr: $crate::MovingPtr<_, _> = $ptr;1457let _ = || {1458let value = &mut *ptr;1459// Ensure that each field index exists and is mentioned only once1460// Ensure that the struct is not `repr(packed)` and that we may take references to fields1461core::hint::black_box(($(&mut value.$field_index,)*));1462// Ensure that `ptr` is a tuple and not something that derefs to it1463// Ensure that the number of patterns matches the number of fields1464fn unreachable<T>(_index: usize) -> T {1465unreachable!()1466}1467*value = ($(unreachable($field_index),)*);1468};1469// SAFETY:1470// - `f` does a raw pointer offset, which always returns a non-null pointer to a field inside `T`1471// - The struct is not `repr(packed)`, since otherwise the block of code above would fail compilation1472// - `mem::forget` is called on `self` immediately after these calls1473// - Each field is distinct, since otherwise the block of code above would fail compilation1474$(let $pattern = unsafe { ptr.move_field(|f| &raw mut (*f).$field_index) };)*1475core::mem::forget(ptr);1476};1477({ let MaybeUninit::<tuple> { $($field_index:tt: $pattern:pat),* $(,)? } = $ptr:expr ;}) => {1478// Specify the type to make sure the `mem::forget` doesn't forget a mere `&mut MovingPtr`1479let mut ptr: $crate::MovingPtr<core::mem::MaybeUninit<_>, _> = $ptr;1480let _ = || {1481// SAFETY: This closure is never called1482let value = unsafe { ptr.assume_init_mut() };1483// Ensure that each field index exists and is mentioned only once1484// Ensure that the struct is not `repr(packed)` and that we may take references to fields1485core::hint::black_box(($(&mut value.$field_index,)*));1486// Ensure that `ptr` is a tuple and not something that derefs to it1487// Ensure that the number of patterns matches the number of fields1488fn unreachable<T>(_index: usize) -> T {1489unreachable!()1490}1491*value = ($(unreachable($field_index),)*);1492};1493// SAFETY:1494// - `f` does a raw pointer offset, which always returns a non-null pointer to a field inside `T`1495// - The struct is not `repr(packed)`, since otherwise the block of code above would fail compilation1496// - `mem::forget` is called on `self` immediately after these calls1497// - Each field is distinct, since otherwise the block of code above would fail compilation1498$(let $pattern = unsafe { ptr.move_maybe_uninit_field(|f| &raw mut (*f).$field_index) };)*1499core::mem::forget(ptr);1500};1501({ let $struct_name:ident { $($field_index:tt$(: $pattern:pat)?),* $(,)? } = $ptr:expr ;}) => {1502// Specify the type to make sure the `mem::forget` doesn't forget a mere `&mut MovingPtr`1503let mut ptr: $crate::MovingPtr<_, _> = $ptr;1504let _ = || {1505let value = &mut *ptr;1506// Ensure that each field index exists is mentioned only once1507// Ensure that each field is on the struct and not accessed using autoref1508let $struct_name { $($field_index: _),* } = value;1509// Ensure that the struct is not `repr(packed)` and that we may take references to fields1510core::hint::black_box(($(&mut value.$field_index),*));1511// Ensure that `ptr` is a `$struct_name` and not just something that derefs to it1512let value: *mut _ = value;1513// SAFETY: This closure is never called1514$struct_name { ..unsafe { value.read() } };1515};1516// SAFETY:1517// - `f` does a raw pointer offset, which always returns a non-null pointer to a field inside `T`1518// - The struct is not `repr(packed)`, since otherwise the block of code above would fail compilation1519// - `mem::forget` is called on `self` immediately after these calls1520// - Each field is distinct, since otherwise the block of code above would fail compilation1521$(let $crate::get_pattern!($field_index$(: $pattern)?) = unsafe { ptr.move_field(|f| &raw mut (*f).$field_index) };)*1522core::mem::forget(ptr);1523};1524({ let MaybeUninit::<$struct_name:ident> { $($field_index:tt$(: $pattern:pat)?),* $(,)? } = $ptr:expr ;}) => {1525// Specify the type to make sure the `mem::forget` doesn't forget a mere `&mut MovingPtr`1526let mut ptr: $crate::MovingPtr<core::mem::MaybeUninit<_>, _> = $ptr;1527let _ = || {1528// SAFETY: This closure is never called1529let value = unsafe { ptr.assume_init_mut() };1530// Ensure that each field index exists is mentioned only once1531// Ensure that each field is on the struct and not accessed using autoref1532let $struct_name { $($field_index: _),* } = value;1533// Ensure that the struct is not `repr(packed)` and that we may take references to fields1534core::hint::black_box(($(&mut value.$field_index),*));1535// Ensure that `ptr` is a `$struct_name` and not just something that derefs to it1536let value: *mut _ = value;1537// SAFETY: This closure is never called1538$struct_name { ..unsafe { value.read() } };1539};1540// SAFETY:1541// - `f` does a raw pointer offset, which always returns a non-null pointer to a field inside `T`1542// - The struct is not `repr(packed)`, since otherwise the block of code above would fail compilation1543// - `mem::forget` is called on `self` immediately after these calls1544// - Each field is distinct, since otherwise the block of code above would fail compilation1545$(let $crate::get_pattern!($field_index$(: $pattern)?) = unsafe { ptr.move_maybe_uninit_field(|f| &raw mut (*f).$field_index) };)*1546core::mem::forget(ptr);1547};1548}154915501551