#![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,15ops::{Deref, DerefMut},16ptr::{self, NonNull},17};1819/// Used as a type argument to [`Ptr`], [`PtrMut`], [`OwningPtr`], and [`MovingPtr`] to specify that the pointer is guaranteed20/// to be [aligned].21///22/// [aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment23#[derive(Debug, Copy, Clone)]24pub struct Aligned;2526/// Used as a type argument to [`Ptr`], [`PtrMut`], [`OwningPtr`], and [`MovingPtr`] to specify that the pointer may not [aligned].27///28/// [aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment29#[derive(Debug, Copy, Clone)]30pub struct Unaligned;3132/// Trait that is only implemented for [`Aligned`] and [`Unaligned`] to work around the lack of ability33/// to have const generics of an enum.34pub trait IsAligned: sealed::Sealed {35/// Reads the value pointed to by `ptr`.36///37/// # Safety38/// - `ptr` must be valid for reads.39/// - `ptr` must point to a valid instance of type `T`40/// - If this type is [`Aligned`], then `ptr` must be [properly aligned] for type `T`.41///42/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment43#[doc(hidden)]44unsafe fn read_ptr<T>(ptr: *const T) -> T;4546/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source47/// and destination must *not* overlap.48///49/// # Safety50/// - `src` must be valid for reads of `count * size_of::<T>()` bytes.51/// - `dst` must be valid for writes of `count * size_of::<T>()` bytes.52/// - The region of memory beginning at `src` with a size of `count *53/// size_of::<T>()` bytes must *not* overlap with the region of memory54/// beginning at `dst` with the same size.55/// - If this type is [`Aligned`], then both `src` and `dst` must properly56/// be aligned for values of type `T`.57#[doc(hidden)]58unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);5960/// Reads the value pointed to by `ptr`.61///62/// # Safety63/// - `ptr` must be valid for reads and writes.64/// - `ptr` must point to a valid instance of type `T`65/// - If this type is [`Aligned`], then `ptr` must be [properly aligned] for type `T`.66/// - The value pointed to by `ptr` must be valid for dropping.67/// - While `drop_in_place` is executing, the only way to access parts of `ptr` is through68/// the `&mut Self` supplied to it's `Drop::drop` impl.69///70/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment71#[doc(hidden)]72unsafe fn drop_in_place<T>(ptr: *mut T);73}7475impl IsAligned for Aligned {76#[inline]77unsafe fn read_ptr<T>(ptr: *const T) -> T {78// SAFETY:79// - The caller is required to ensure that `src` must be valid for reads.80// - The caller is required to ensure that `src` points to a valid instance of type `T`.81// - This type is `Aligned` so the caller must ensure that `src` is properly aligned for type `T`.82unsafe { ptr.read() }83}8485#[inline]86unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {87// SAFETY:88// - The caller is required to ensure that `src` must be valid for reads.89// - The caller is required to ensure that `dst` must be valid for writes.90// - The caller is required to ensure that `src` and `dst` are aligned.91// - The caller is required to ensure that the memory region covered by `src`92// and `dst`, fitting up to `count` elements do not overlap.93unsafe {94ptr::copy_nonoverlapping(src, dst, count);95}96}9798#[inline]99unsafe fn drop_in_place<T>(ptr: *mut T) {100// SAFETY:101// - The caller is required to ensure that `ptr` must be valid for reads and writes.102// - The caller is required to ensure that `ptr` points to a valid instance of type `T`.103// - This type is `Aligned` so the caller must ensure that `ptr` is properly aligned for type `T`.104// - The caller is required to ensure that `ptr` points must be valid for dropping.105// - The caller is required to ensure that the value `ptr` points must not be used after this function106// call.107unsafe {108ptr::drop_in_place(ptr);109}110}111}112113impl IsAligned for Unaligned {114#[inline]115unsafe fn read_ptr<T>(ptr: *const T) -> T {116// SAFETY:117// - The caller is required to ensure that `src` must be valid for reads.118// - The caller is required to ensure that `src` points to a valid instance of type `T`.119unsafe { ptr.read_unaligned() }120}121122#[inline]123unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {124// SAFETY:125// - The caller is required to ensure that `src` must be valid for reads.126// - The caller is required to ensure that `dst` must be valid for writes.127// - This is doing a byte-wise copy. `src` and `dst` are always guaranteed to be128// aligned.129// - The caller is required to ensure that the memory region covered by `src`130// and `dst`, fitting up to `count` elements do not overlap.131unsafe {132ptr::copy_nonoverlapping::<u8>(133src.cast::<u8>(),134dst.cast::<u8>(),135count * size_of::<T>(),136);137}138}139140#[inline]141unsafe fn drop_in_place<T>(ptr: *mut T) {142// SAFETY:143// - The caller is required to ensure that `ptr` must be valid for reads and writes.144// - The caller is required to ensure that `ptr` points to a valid instance of type `T`.145// - This type is not `Aligned` so the caller does not need to ensure that `ptr` is properly aligned for type `T`.146// - The caller is required to ensure that `ptr` points must be valid for dropping.147// - The caller is required to ensure that the value `ptr` points must not be used after this function148// call.149unsafe {150drop(ptr.read_unaligned());151}152}153}154155mod sealed {156pub trait Sealed {}157impl Sealed for super::Aligned {}158impl Sealed for super::Unaligned {}159}160161/// A newtype around [`NonNull`] that only allows conversion to read-only borrows or pointers.162///163/// This type can be thought of as the `*const T` to [`NonNull<T>`]'s `*mut T`.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 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 exctra 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 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 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 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 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 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 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 performance reasons1059pub struct ThinSlicePtr<'a, T> {1060ptr: NonNull<T>,1061#[cfg(debug_assertions)]1062len: usize,1063_marker: PhantomData<&'a [T]>,1064}10651066impl<'a, T> ThinSlicePtr<'a, T> {1067#[inline]1068/// Indexes the slice without doing bounds checks1069///1070/// # Safety1071/// `index` must be in-bounds.1072pub unsafe fn get(self, index: usize) -> &'a T {1073#[cfg(debug_assertions)]1074debug_assert!(index < self.len);10751076let ptr = self.ptr.as_ptr();1077// SAFETY: `index` is in-bounds so the resulting pointer is valid to dereference.1078unsafe { &*ptr.add(index) }1079}1080}10811082impl<'a, T> Clone for ThinSlicePtr<'a, T> {1083fn clone(&self) -> Self {1084*self1085}1086}10871088impl<'a, T> Copy for ThinSlicePtr<'a, T> {}10891090impl<'a, T> From<&'a [T]> for ThinSlicePtr<'a, T> {1091#[inline]1092fn from(slice: &'a [T]) -> Self {1093let ptr = slice.as_ptr().cast_mut();1094Self {1095// SAFETY: a reference can never be null1096ptr: unsafe { NonNull::new_unchecked(ptr.debug_ensure_aligned()) },1097#[cfg(debug_assertions)]1098len: slice.len(),1099_marker: PhantomData,1100}1101}1102}11031104/// Creates a dangling pointer with specified alignment.1105/// See [`NonNull::dangling`].1106pub const fn dangling_with_align(align: NonZeroUsize) -> NonNull<u8> {1107debug_assert!(align.is_power_of_two(), "Alignment must be power of two.");1108// SAFETY: The pointer will not be null, since it was created1109// from the address of a `NonZero<usize>`.1110// TODO: use https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.with_addr once stabilized1111unsafe { NonNull::new_unchecked(ptr::null_mut::<u8>().wrapping_add(align.get())) }1112}11131114mod private {1115use core::cell::UnsafeCell;11161117pub trait SealedUnsafeCell {}1118impl<'a, T> SealedUnsafeCell for &'a UnsafeCell<T> {}1119}11201121/// Extension trait for helper methods on [`UnsafeCell`]1122pub trait UnsafeCellDeref<'a, T>: private::SealedUnsafeCell {1123/// # Safety1124/// - The returned value must be unique and not alias any mutable or immutable references to the contents of the [`UnsafeCell`].1125/// - 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).1126unsafe fn deref_mut(self) -> &'a mut T;11271128/// # Safety1129/// - For the lifetime `'a` of the returned value you must not construct a mutable reference to the contents of the [`UnsafeCell`].1130/// - 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).1131unsafe fn deref(self) -> &'a T;11321133/// Returns a copy of the contained value.1134///1135/// # Safety1136/// - The [`UnsafeCell`] must not currently have a mutable reference to its content.1137/// - 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).1138unsafe fn read(self) -> T1139where1140T: Copy;1141}11421143impl<'a, T> UnsafeCellDeref<'a, T> for &'a UnsafeCell<T> {1144#[inline]1145unsafe fn deref_mut(self) -> &'a mut T {1146// SAFETY: The caller upholds the alias rules.1147unsafe { &mut *self.get() }1148}1149#[inline]1150unsafe fn deref(self) -> &'a T {1151// SAFETY: The caller upholds the alias rules.1152unsafe { &*self.get() }1153}11541155#[inline]1156unsafe fn read(self) -> T1157where1158T: Copy,1159{1160// SAFETY: The caller upholds the alias rules.1161unsafe { self.get().read() }1162}1163}11641165trait DebugEnsureAligned {1166fn debug_ensure_aligned(self) -> Self;1167}11681169// Disable this for miri runs as it already checks if pointer to reference1170// casts are properly aligned.1171#[cfg(all(debug_assertions, not(miri)))]1172impl<T: Sized> DebugEnsureAligned for *mut T {1173#[track_caller]1174fn debug_ensure_aligned(self) -> Self {1175let align = align_of::<T>();1176// Implementation shamelessly borrowed from the currently unstable1177// ptr.is_aligned_to.1178//1179// Replace once https://github.com/rust-lang/rust/issues/96284 is stable.1180assert_eq!(1181self as usize & (align - 1),11820,1183"pointer is not aligned. Address {:p} does not have alignment {} for type {}",1184self,1185align,1186core::any::type_name::<T>()1187);1188self1189}1190}11911192#[cfg(any(not(debug_assertions), miri))]1193impl<T: Sized> DebugEnsureAligned for *mut T {1194#[inline(always)]1195fn debug_ensure_aligned(self) -> Self {1196self1197}1198}11991200/// Safely converts a owned value into a [`MovingPtr`] while minimizing the number of stack copies.1201///1202/// This cannot be used as expression and must be used as a statement. Internally this macro works via variable shadowing.1203#[macro_export]1204macro_rules! move_as_ptr {1205($value: ident) => {1206let mut $value = core::mem::MaybeUninit::new($value);1207// SAFETY:1208// - This macro shadows a MaybeUninit value that took ownership of the original value.1209// it is impossible to refer to the original value, preventing further access after1210// the `MovingPtr` has been used. `MaybeUninit` also prevents the compiler from1211// dropping the original value.1212let $value = unsafe { $crate::MovingPtr::from_value(&mut $value) };1213};1214}12151216/// Helper macro used by [`deconstruct_moving_ptr`] to to extract1217/// the pattern from `field: pattern` or `field` shorthand.1218#[macro_export]1219#[doc(hidden)]1220macro_rules! get_pattern {1221($field_index:tt) => {1222$field_index1223};1224($field_index:tt: $pattern:pat) => {1225$pattern1226};1227}12281229/// Deconstructs a [`MovingPtr`] into its individual fields.1230///1231/// This consumes the [`MovingPtr`] and hands out [`MovingPtr`] wrappers around1232/// pointers to each of its fields. The value will *not* be dropped.1233///1234/// The macro should wrap a `let` expression with a struct pattern.1235/// It does not support matching tuples by position,1236/// so for tuple structs you should use `0: pat` syntax.1237///1238/// For tuples themselves, pass the identifier `tuple` instead of the struct name,1239/// like `let tuple { 0: pat0, 1: pat1 } = value`.1240///1241/// This can also project into `MaybeUninit`.1242/// Wrap the type name or `tuple` with `MaybeUninit::<_>`,1243/// and the macro will deconstruct a `MovingPtr<MaybeUninit<ParentType>>`1244/// into `MovingPtr<MaybeUninit<FieldType>>` values.1245///1246/// # Examples1247///1248/// ## Structs1249///1250/// ```1251/// use core::mem::{offset_of, MaybeUninit};1252/// use bevy_ptr::{MovingPtr, move_as_ptr};1253/// # use bevy_ptr::Unaligned;1254/// # struct FieldAType(usize);1255/// # struct FieldBType(usize);1256/// # struct FieldCType(usize);1257///1258/// # pub struct Parent {1259/// # pub field_a: FieldAType,1260/// # pub field_b: FieldBType,1261/// # pub field_c: FieldCType,1262/// # }1263///1264/// let parent = Parent {1265/// field_a: FieldAType(11),1266/// field_b: FieldBType(22),1267/// field_c: FieldCType(33),1268/// };1269///1270/// let mut target_a = FieldAType(101);1271/// let mut target_b = FieldBType(102);1272/// let mut target_c = FieldCType(103);1273///1274/// // Converts `parent` into a `MovingPtr`1275/// move_as_ptr!(parent);1276///1277/// // The field names must match the name used in the type definition.1278/// // Each one will be a `MovingPtr` of the field's type.1279/// bevy_ptr::deconstruct_moving_ptr!({1280/// let Parent { field_a, field_b, field_c } = parent;1281/// });1282///1283/// field_a.assign_to(&mut target_a);1284/// field_b.assign_to(&mut target_b);1285/// field_c.assign_to(&mut target_c);1286///1287/// assert_eq!(target_a.0, 11);1288/// assert_eq!(target_b.0, 22);1289/// assert_eq!(target_c.0, 33);1290/// ```1291///1292/// ## Tuples1293///1294/// ```1295/// use core::mem::{offset_of, MaybeUninit};1296/// use bevy_ptr::{MovingPtr, move_as_ptr};1297/// # use bevy_ptr::Unaligned;1298/// # struct FieldAType(usize);1299/// # struct FieldBType(usize);1300/// # struct FieldCType(usize);1301///1302/// # pub struct Parent {1303/// # pub field_a: FieldAType,1304/// # pub field_b: FieldBType,1305/// # pub field_c: FieldCType,1306/// # }1307///1308/// let parent = (1309/// FieldAType(11),1310/// FieldBType(22),1311/// FieldCType(33),1312/// );1313///1314/// let mut target_a = FieldAType(101);1315/// let mut target_b = FieldBType(102);1316/// let mut target_c = FieldCType(103);1317///1318/// // Converts `parent` into a `MovingPtr`1319/// move_as_ptr!(parent);1320///1321/// // The field names must match the name used in the type definition.1322/// // Each one will be a `MovingPtr` of the field's type.1323/// bevy_ptr::deconstruct_moving_ptr!({1324/// let tuple { 0: field_a, 1: field_b, 2: field_c } = parent;1325/// });1326///1327/// field_a.assign_to(&mut target_a);1328/// field_b.assign_to(&mut target_b);1329/// field_c.assign_to(&mut target_c);1330///1331/// assert_eq!(target_a.0, 11);1332/// assert_eq!(target_b.0, 22);1333/// assert_eq!(target_c.0, 33);1334/// ```1335///1336/// ## `MaybeUninit`1337///1338/// ```1339/// use core::mem::{offset_of, MaybeUninit};1340/// use bevy_ptr::{MovingPtr, move_as_ptr};1341/// # use bevy_ptr::Unaligned;1342/// # struct FieldAType(usize);1343/// # struct FieldBType(usize);1344/// # struct FieldCType(usize);1345///1346/// # pub struct Parent {1347/// # pub field_a: FieldAType,1348/// # pub field_b: FieldBType,1349/// # pub field_c: FieldCType,1350/// # }1351///1352/// let parent = MaybeUninit::new(Parent {1353/// field_a: FieldAType(11),1354/// field_b: FieldBType(22),1355/// field_c: FieldCType(33),1356/// });1357///1358/// let mut target_a = MaybeUninit::new(FieldAType(101));1359/// let mut target_b = MaybeUninit::new(FieldBType(102));1360/// let mut target_c = MaybeUninit::new(FieldCType(103));1361///1362/// // Converts `parent` into a `MovingPtr`1363/// move_as_ptr!(parent);1364///1365/// // The field names must match the name used in the type definition.1366/// // Each one will be a `MovingPtr` of the field's type.1367/// bevy_ptr::deconstruct_moving_ptr!({1368/// let MaybeUninit::<Parent> { field_a, field_b, field_c } = parent;1369/// });1370///1371/// field_a.assign_to(&mut target_a);1372/// field_b.assign_to(&mut target_b);1373/// field_c.assign_to(&mut target_c);1374///1375/// unsafe {1376/// assert_eq!(target_a.assume_init().0, 11);1377/// assert_eq!(target_b.assume_init().0, 22);1378/// assert_eq!(target_c.assume_init().0, 33);1379/// }1380/// ```1381///1382/// [`assign_to`]: MovingPtr::assign_to1383#[macro_export]1384macro_rules! deconstruct_moving_ptr {1385({ let tuple { $($field_index:tt: $pattern:pat),* $(,)? } = $ptr:expr ;}) => {1386// Specify the type to make sure the `mem::forget` doesn't forget a mere `&mut MovingPtr`1387let mut ptr: $crate::MovingPtr<_, _> = $ptr;1388let _ = || {1389let value = &mut *ptr;1390// Ensure that each field index exists and is mentioned only once1391// Ensure that the struct is not `repr(packed)` and that we may take references to fields1392core::hint::black_box(($(&mut value.$field_index,)*));1393// Ensure that `ptr` is a tuple and not something that derefs to it1394// Ensure that the number of patterns matches the number of fields1395fn unreachable<T>(_index: usize) -> T {1396unreachable!()1397}1398*value = ($(unreachable($field_index),)*);1399};1400// SAFETY:1401// - `f` does a raw pointer offset, which always returns a non-null pointer to a field inside `T`1402// - The struct is not `repr(packed)`, since otherwise the block of code above would fail compilation1403// - `mem::forget` is called on `self` immediately after these calls1404// - Each field is distinct, since otherwise the block of code above would fail compilation1405$(let $pattern = unsafe { ptr.move_field(|f| &raw mut (*f).$field_index) };)*1406core::mem::forget(ptr);1407};1408({ let MaybeUninit::<tuple> { $($field_index:tt: $pattern:pat),* $(,)? } = $ptr:expr ;}) => {1409// Specify the type to make sure the `mem::forget` doesn't forget a mere `&mut MovingPtr`1410let mut ptr: $crate::MovingPtr<core::mem::MaybeUninit<_>, _> = $ptr;1411let _ = || {1412// SAFETY: This closure is never called1413let value = unsafe { ptr.assume_init_mut() };1414// Ensure that each field index exists and is mentioned only once1415// Ensure that the struct is not `repr(packed)` and that we may take references to fields1416core::hint::black_box(($(&mut value.$field_index,)*));1417// Ensure that `ptr` is a tuple and not something that derefs to it1418// Ensure that the number of patterns matches the number of fields1419fn unreachable<T>(_index: usize) -> T {1420unreachable!()1421}1422*value = ($(unreachable($field_index),)*);1423};1424// SAFETY:1425// - `f` does a raw pointer offset, which always returns a non-null pointer to a field inside `T`1426// - The struct is not `repr(packed)`, since otherwise the block of code above would fail compilation1427// - `mem::forget` is called on `self` immediately after these calls1428// - Each field is distinct, since otherwise the block of code above would fail compilation1429$(let $pattern = unsafe { ptr.move_maybe_uninit_field(|f| &raw mut (*f).$field_index) };)*1430core::mem::forget(ptr);1431};1432({ let $struct_name:ident { $($field_index:tt$(: $pattern:pat)?),* $(,)? } = $ptr:expr ;}) => {1433// Specify the type to make sure the `mem::forget` doesn't forget a mere `&mut MovingPtr`1434let mut ptr: $crate::MovingPtr<_, _> = $ptr;1435let _ = || {1436let value = &mut *ptr;1437// Ensure that each field index exists is mentioned only once1438// Ensure that each field is on the struct and not accessed using autoref1439let $struct_name { $($field_index: _),* } = value;1440// Ensure that the struct is not `repr(packed)` and that we may take references to fields1441core::hint::black_box(($(&mut value.$field_index),*));1442// Ensure that `ptr` is a `$struct_name` and not just something that derefs to it1443let value: *mut _ = value;1444// SAFETY: This closure is never called1445$struct_name { ..unsafe { value.read() } };1446};1447// SAFETY:1448// - `f` does a raw pointer offset, which always returns a non-null pointer to a field inside `T`1449// - The struct is not `repr(packed)`, since otherwise the block of code above would fail compilation1450// - `mem::forget` is called on `self` immediately after these calls1451// - Each field is distinct, since otherwise the block of code above would fail compilation1452$(let $crate::get_pattern!($field_index$(: $pattern)?) = unsafe { ptr.move_field(|f| &raw mut (*f).$field_index) };)*1453core::mem::forget(ptr);1454};1455({ let MaybeUninit::<$struct_name:ident> { $($field_index:tt$(: $pattern:pat)?),* $(,)? } = $ptr:expr ;}) => {1456// Specify the type to make sure the `mem::forget` doesn't forget a mere `&mut MovingPtr`1457let mut ptr: $crate::MovingPtr<core::mem::MaybeUninit<_>, _> = $ptr;1458let _ = || {1459// SAFETY: This closure is never called1460let value = unsafe { ptr.assume_init_mut() };1461// Ensure that each field index exists is mentioned only once1462// Ensure that each field is on the struct and not accessed using autoref1463let $struct_name { $($field_index: _),* } = value;1464// Ensure that the struct is not `repr(packed)` and that we may take references to fields1465core::hint::black_box(($(&mut value.$field_index),*));1466// Ensure that `ptr` is a `$struct_name` and not just something that derefs to it1467let value: *mut _ = value;1468// SAFETY: This closure is never called1469$struct_name { ..unsafe { value.read() } };1470};1471// SAFETY:1472// - `f` does a raw pointer offset, which always returns a non-null pointer to a field inside `T`1473// - The struct is not `repr(packed)`, since otherwise the block of code above would fail compilation1474// - `mem::forget` is called on `self` immediately after these calls1475// - Each field is distinct, since otherwise the block of code above would fail compilation1476$(let $crate::get_pattern!($field_index$(: $pattern)?) = unsafe { ptr.move_maybe_uninit_field(|f| &raw mut (*f).$field_index) };)*1477core::mem::forget(ptr);1478};1479}148014811482