Skip to main content

bevy_ptr/
lib.rs

1#![doc = include_str!("../README.md")]
2#![no_std]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4#![expect(unsafe_code, reason = "Raw pointers are inherently unsafe.")]
5#![doc(
6    html_logo_url = "https://bevy.org/assets/icon.png",
7    html_favicon_url = "https://bevy.org/assets/icon.png"
8)]
9
10use core::{
11    cell::UnsafeCell,
12    fmt::{self, Debug, Formatter, Pointer},
13    marker::PhantomData,
14    mem::{self, ManuallyDrop, MaybeUninit},
15    ops::{Deref, DerefMut, Range},
16    ptr::{self, NonNull},
17};
18
19/// Used as a type argument to [`Ptr`], [`PtrMut`], [`OwningPtr`], and [`MovingPtr`] to specify that the pointer is guaranteed
20/// to be [aligned].
21///
22/// [aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
23#[derive(Debug, Copy, Clone)]
24pub struct Aligned;
25
26/// 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#alignment
29#[derive(Debug, Copy, Clone)]
30pub struct Unaligned;
31
32/// Trait that is only implemented for [`Aligned`] and [`Unaligned`] to work around the lack of ability
33/// to have const generics of an enum.
34pub trait IsAligned: sealed::Sealed {
35    /// Reads the value pointed to by `ptr`.
36    ///
37    /// # Safety
38    ///  - `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#alignment
43    #[doc(hidden)]
44    unsafe fn read_ptr<T>(ptr: *const T) -> T;
45
46    /// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
47    /// and destination must *not* overlap.
48    ///
49    /// # Safety
50    ///  - `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 memory
54    ///    beginning at `dst` with the same size.
55    ///  - If this type is [`Aligned`], then both `src` and `dst` must properly
56    ///    be aligned for values of type `T`.
57    #[doc(hidden)]
58    unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
59
60    /// Reads the value pointed to by `ptr`.
61    ///
62    /// # Safety
63    ///  - `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 through
68    ///    the `&mut Self` supplied to it's `Drop::drop` impl.
69    ///
70    /// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
71    #[doc(hidden)]
72    unsafe fn drop_in_place<T>(ptr: *mut T);
73}
74
75impl IsAligned for Aligned {
76    #[inline]
77    unsafe 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`.
82        unsafe { ptr.read() }
83    }
84
85    #[inline]
86    unsafe 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.
93        unsafe {
94            ptr::copy_nonoverlapping(src, dst, count);
95        }
96    }
97
98    #[inline]
99    unsafe 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 function
106        //    call.
107        unsafe {
108            ptr::drop_in_place(ptr);
109        }
110    }
111}
112
113impl IsAligned for Unaligned {
114    #[inline]
115    unsafe 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`.
119        unsafe { ptr.read_unaligned() }
120    }
121
122    #[inline]
123    unsafe 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 be
128        //    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.
131        unsafe {
132            ptr::copy_nonoverlapping::<u8>(
133                src.cast::<u8>(),
134                dst.cast::<u8>(),
135                count * size_of::<T>(),
136            );
137        }
138    }
139
140    #[inline]
141    unsafe 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 function
148        //    call.
149        unsafe {
150            drop(ptr.read_unaligned());
151        }
152    }
153}
154
155mod sealed {
156    pub trait Sealed {}
157    impl Sealed for super::Aligned {}
158    impl Sealed for super::Unaligned {}
159}
160
161/// 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#[derive(Clone, Copy)]
165#[repr(transparent)]
166pub struct ConstNonNull<T: ?Sized>(NonNull<T>);
167
168impl<T: ?Sized> ConstNonNull<T> {
169    /// Creates a new `ConstNonNull` if `ptr` is non-null.
170    ///
171    /// # Examples
172    ///
173    /// ```
174    /// use bevy_ptr::ConstNonNull;
175    ///
176    /// let x = 0u32;
177    /// let ptr = ConstNonNull::<u32>::new(&x as *const _).expect("ptr is null!");
178    ///
179    /// if let Some(ptr) = ConstNonNull::<u32>::new(core::ptr::null()) {
180    ///     unreachable!();
181    /// }
182    /// ```
183    pub fn new(ptr: *const T) -> Option<Self> {
184        NonNull::new(ptr.cast_mut()).map(Self)
185    }
186
187    /// Creates a new `ConstNonNull`.
188    ///
189    /// # Safety
190    ///
191    /// `ptr` must be non-null.
192    ///
193    /// # Examples
194    ///
195    /// ```
196    /// use bevy_ptr::ConstNonNull;
197    ///
198    /// let x = 0u32;
199    /// let ptr = unsafe { ConstNonNull::new_unchecked(&x as *const _) };
200    /// ```
201    ///
202    /// *Incorrect* usage of this function:
203    ///
204    /// ```rust,no_run
205    /// use bevy_ptr::ConstNonNull;
206    ///
207    /// // NEVER DO THAT!!! This is undefined behavior. ⚠️
208    /// let ptr = unsafe { ConstNonNull::<u32>::new_unchecked(core::ptr::null()) };
209    /// ```
210    pub const unsafe fn new_unchecked(ptr: *const T) -> Self {
211        // SAFETY: This function's safety invariants are identical to `NonNull::new_unchecked`
212        // The caller must satisfy all of them.
213        unsafe { Self(NonNull::new_unchecked(ptr.cast_mut())) }
214    }
215
216    /// Returns a shared reference to the value.
217    ///
218    /// # Safety
219    ///
220    /// When calling this method, you have to ensure that all of the following is true:
221    ///
222    /// * The pointer must be [properly aligned].
223    ///
224    /// * It must be "dereferenceable" in the sense defined in [the `core::ptr` documentation].
225    ///
226    /// * The pointer must point to an initialized instance of `T`.
227    ///
228    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
229    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
230    ///   In particular, while this reference exists, the memory the pointer points to must
231    ///   not get mutated (except inside `UnsafeCell`).
232    ///
233    /// This applies even if the result of this method is unused!
234    /// (The part about being initialized is not yet fully decided, but until
235    /// it is, the only safe approach is to ensure that they are indeed initialized.)
236    ///
237    /// # Examples
238    ///
239    /// ```
240    /// use bevy_ptr::ConstNonNull;
241    ///
242    /// let mut x = 0u32;
243    /// let ptr = ConstNonNull::new(&mut x as *mut _).expect("ptr is null!");
244    ///
245    /// let ref_x = unsafe { ptr.as_ref() };
246    /// println!("{ref_x}");
247    /// ```
248    ///
249    /// [the `core::ptr` documentation]: core::ptr#safety
250    /// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
251    #[inline]
252    pub unsafe fn as_ref<'a>(&self) -> &'a T {
253        // SAFETY: This function's safety invariants are identical to `NonNull::as_ref`
254        // The caller must satisfy all of them.
255        unsafe { self.0.as_ref() }
256    }
257}
258
259impl<T: ?Sized> From<NonNull<T>> for ConstNonNull<T> {
260    fn from(value: NonNull<T>) -> ConstNonNull<T> {
261        ConstNonNull(value)
262    }
263}
264
265impl<'a, T: ?Sized> From<&'a T> for ConstNonNull<T> {
266    fn from(value: &'a T) -> ConstNonNull<T> {
267        ConstNonNull(NonNull::from(value))
268    }
269}
270
271impl<'a, T: ?Sized> From<&'a mut T> for ConstNonNull<T> {
272    fn from(value: &'a mut T) -> ConstNonNull<T> {
273        ConstNonNull(NonNull::from(value))
274    }
275}
276
277/// Type-erased borrow of some unknown type chosen when constructing this type.
278///
279/// This type tries to act "borrow-like" which means that:
280/// - It should be considered immutable: its target must not be changed while this pointer is alive.
281/// - It must always point to a valid value of whatever the pointee type is.
282/// - The lifetime `'a` accurately represents how long the pointer is valid for.
283/// - If `A` is [`Aligned`], the pointer must always be [properly aligned] for the unknown pointee type.
284///
285/// It may be helpful to think of this type as similar to `&'a dyn Any` but without
286/// the metadata and able to point to data that does not correspond to a Rust type.
287///
288/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
289#[derive(Copy, Clone)]
290#[repr(transparent)]
291pub struct Ptr<'a, A: IsAligned = Aligned>(NonNull<u8>, PhantomData<(&'a u8, A)>);
292
293/// Type-erased mutable borrow of some unknown type chosen when constructing this type.
294///
295/// This type tries to act "borrow-like" which means that:
296/// - Pointer is considered exclusive and mutable. It cannot be cloned as this would lead to
297///   aliased mutability.
298/// - It must always point to a valid value of whatever the pointee type is.
299/// - The lifetime `'a` accurately represents how long the pointer is valid for.
300/// - If `A` is [`Aligned`], the pointer must always be [properly aligned] for the unknown pointee type.
301///
302/// It may be helpful to think of this type as similar to `&'a mut dyn Any` but without
303/// the metadata and able to point to data that does not correspond to a Rust type.
304///
305/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
306#[repr(transparent)]
307pub struct PtrMut<'a, A: IsAligned = Aligned>(NonNull<u8>, PhantomData<(&'a mut u8, A)>);
308
309/// Type-erased [`Box`]-like pointer to some unknown type chosen when constructing this type.
310///
311/// Conceptually represents ownership of whatever data is being pointed to and so is
312/// responsible for calling its `Drop` impl. This pointer is _not_ responsible for freeing
313/// the memory pointed to by this pointer as it may be pointing to an element in a `Vec` or
314/// to a local in a function etc.
315///
316/// This type tries to act "borrow-like" which means that:
317/// - Pointer should be considered exclusive and mutable. It cannot be cloned as this would lead
318///   to aliased mutability and potentially use after free bugs.
319/// - It must always point to a valid value of whatever the pointee type is.
320/// - The lifetime `'a` accurately represents how long the pointer is valid for.
321/// - If `A` is [`Aligned`], the pointer must always be [properly aligned] for the unknown pointee type.
322///
323/// It may be helpful to think of this type as similar to `&'a mut ManuallyDrop<dyn Any>` but
324/// without the metadata and able to point to data that does not correspond to a Rust type.
325///
326/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
327/// [`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html
328#[repr(transparent)]
329pub struct OwningPtr<'a, A: IsAligned = Aligned>(NonNull<u8>, PhantomData<(&'a mut u8, A)>);
330
331/// A [`Box`]-like pointer for moving a value to a new memory location without needing to pass by
332/// value.
333///
334/// Conceptually represents ownership of whatever data is being pointed to and will call its
335/// [`Drop`] impl upon being dropped. This pointer is _not_ responsible for freeing
336/// the memory pointed to by this pointer as it may be pointing to an element in a `Vec` or
337/// to a local in a function etc.
338///
339/// This type tries to act "borrow-like" which means that:
340/// - Pointer should be considered exclusive and mutable. It cannot be cloned as this would lead
341///   to aliased mutability and potentially use after free bugs.
342/// - It must always point to a valid value of whatever the pointee type is.
343/// - The lifetime `'a` accurately represents how long the pointer is valid for.
344/// - It does not support pointer arithmetic in any way.
345/// - If `A` is [`Aligned`], the pointer must always be [properly aligned] for the type `T`.
346///
347/// A value can be deconstructed into its fields via [`deconstruct_moving_ptr`], see it's documentation
348/// for an example on how to use it.
349///
350/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
351/// [`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html
352#[repr(transparent)]
353pub struct MovingPtr<'a, T, A: IsAligned = Aligned>(NonNull<T>, PhantomData<(&'a mut T, A)>);
354
355macro_rules! impl_ptr {
356    ($ptr:ident) => {
357        impl<'a> $ptr<'a, Aligned> {
358            /// Removes the alignment requirement of this pointer
359            pub fn to_unaligned(self) -> $ptr<'a, Unaligned> {
360                $ptr(self.0, PhantomData)
361            }
362        }
363
364        impl<'a, A: IsAligned> From<$ptr<'a, A>> for NonNull<u8> {
365            fn from(ptr: $ptr<'a, A>) -> Self {
366                ptr.0
367            }
368        }
369
370        impl<A: IsAligned> $ptr<'_, A> {
371            /// Calculates the offset from a pointer.
372            /// As the pointer is type-erased, there is no size information available. The provided
373            /// `count` parameter is in raw bytes.
374            ///
375            /// *See also: [`ptr::offset`][ptr_offset]*
376            ///
377            /// # Safety
378            /// - The offset cannot make the existing ptr null, or take it out of bounds for its allocation.
379            /// - If the `A` type parameter is [`Aligned`] then the offset must not make the resulting pointer
380            ///   be unaligned for the pointee type.
381            /// - The value pointed by the resulting pointer must outlive the lifetime of this pointer.
382            ///
383            /// [ptr_offset]: https://doc.rust-lang.org/std/primitive.pointer.html#method.offset
384            #[inline]
385            pub unsafe fn byte_offset(self, count: isize) -> Self {
386                Self(
387                    // SAFETY: The caller upholds safety for `offset` and ensures the result is not null.
388                    unsafe { NonNull::new_unchecked(self.0.as_ptr().offset(count)) },
389                    PhantomData,
390                )
391            }
392
393            /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
394            /// As the pointer is type-erased, there is no size information available. The provided
395            /// `count` parameter is in raw bytes.
396            ///
397            /// *See also: [`ptr::add`][ptr_add]*
398            ///
399            /// # Safety
400            /// - The offset cannot make the existing ptr null, or take it out of bounds for its allocation.
401            /// - If the `A` type parameter is [`Aligned`] then the offset must not make the resulting pointer
402            ///   be unaligned for the pointee type.
403            /// - The value pointed by the resulting pointer must outlive the lifetime of this pointer.
404            ///
405            /// [ptr_add]: https://doc.rust-lang.org/std/primitive.pointer.html#method.add
406            #[inline]
407            pub unsafe fn byte_add(self, count: usize) -> Self {
408                Self(
409                    // SAFETY: The caller upholds safety for `add` and ensures the result is not null.
410                    unsafe { NonNull::new_unchecked(self.0.as_ptr().add(count)) },
411                    PhantomData,
412                )
413            }
414        }
415
416        impl<A: IsAligned> Pointer for $ptr<'_, A> {
417            #[inline]
418            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
419                Pointer::fmt(&self.0, f)
420            }
421        }
422
423        impl Debug for $ptr<'_, Aligned> {
424            #[inline]
425            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
426                write!(f, "{}<Aligned>({:?})", stringify!($ptr), self.0)
427            }
428        }
429
430        impl Debug for $ptr<'_, Unaligned> {
431            #[inline]
432            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
433                write!(f, "{}<Unaligned>({:?})", stringify!($ptr), self.0)
434            }
435        }
436    };
437}
438
439impl_ptr!(Ptr);
440impl_ptr!(PtrMut);
441impl_ptr!(OwningPtr);
442
443impl<'a, T> MovingPtr<'a, T, Aligned> {
444    /// Removes the alignment requirement of this pointer
445    #[inline]
446    pub fn to_unaligned(self) -> MovingPtr<'a, T, Unaligned> {
447        let value = MovingPtr(self.0, PhantomData);
448        mem::forget(self);
449        value
450    }
451
452    /// Creates a [`MovingPtr`] from a provided value of type `T`.
453    ///
454    /// For a safer alternative, it is strongly advised to use [`move_as_ptr`] where possible.
455    ///
456    /// # Safety
457    /// - `value` must store a properly initialized value of type `T`.
458    /// - Once the returned [`MovingPtr`] has been used, `value` must be treated as
459    ///   it were uninitialized unless it was explicitly leaked via [`core::mem::forget`].
460    #[inline]
461    pub unsafe fn from_value(value: &'a mut MaybeUninit<T>) -> Self {
462        // SAFETY:
463        // - MaybeUninit<T> has the same memory layout as T
464        // - The caller guarantees that `value` must point to a valid instance of type `T`.
465        MovingPtr(NonNull::from(value).cast::<T>(), PhantomData)
466    }
467}
468
469impl<'a, T, A: IsAligned> MovingPtr<'a, T, A> {
470    /// Creates a new instance from a raw pointer.
471    ///
472    /// For a safer alternative, it is strongly advised to use [`move_as_ptr`] where possible.
473    ///
474    /// # Safety
475    /// - `inner` must point to valid value of `T`.
476    /// - If the `A` type parameter is [`Aligned`] then `inner` must be [properly aligned] for `T`.
477    /// - `inner` must have correct provenance to allow read and writes of the pointee type.
478    /// - The lifetime `'a` must be constrained such that this [`MovingPtr`] will stay valid and nothing
479    ///   else can read or mutate the pointee while this [`MovingPtr`] is live.
480    ///
481    /// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
482    #[inline]
483    pub unsafe fn new(inner: NonNull<T>) -> Self {
484        Self(inner, PhantomData)
485    }
486
487    /// Partially moves out some fields inside of `self`.
488    ///
489    /// The partially returned value is returned back pointing to [`MaybeUninit<T>`].
490    ///
491    /// While calling this function is safe, care must be taken with the returned `MovingPtr` as it
492    /// points to a value that may no longer be completely valid.
493    ///
494    /// # Example
495    ///
496    /// ```
497    /// use core::mem::{offset_of, MaybeUninit, forget};
498    /// use bevy_ptr::{MovingPtr, move_as_ptr};
499    /// # struct FieldAType(usize);
500    /// # struct FieldBType(usize);
501    /// # struct FieldCType(usize);
502    /// # fn insert<T>(_ptr: MovingPtr<'_, T>) {}
503    ///
504    /// struct Parent {
505    ///   field_a: FieldAType,
506    ///   field_b: FieldBType,
507    ///   field_c: FieldCType,
508    /// }
509    ///
510    /// # let parent = Parent {
511    /// #   field_a: FieldAType(0),
512    /// #   field_b: FieldBType(0),
513    /// #   field_c: FieldCType(0),
514    /// # };
515    ///
516    /// // Converts `parent` into a `MovingPtr`
517    /// move_as_ptr!(parent);
518    ///
519    /// // SAFETY:
520    /// // - `field_a` and `field_b` are both unique.
521    /// let (partial_parent, ()) = MovingPtr::partial_move(parent, |parent_ptr| unsafe {
522    ///   bevy_ptr::deconstruct_moving_ptr!({
523    ///     let Parent { field_a, field_b, field_c } = parent_ptr;
524    ///   });
525    ///
526    ///   insert(field_a);
527    ///   insert(field_b);
528    ///   forget(field_c);
529    /// });
530    ///
531    /// // Move the rest of fields out of the parent.
532    /// // SAFETY:
533    /// // - `field_c` is by itself unique and does not conflict with the previous accesses
534    /// //   inside `partial_move`.
535    /// unsafe {
536    ///   bevy_ptr::deconstruct_moving_ptr!({
537    ///     let MaybeUninit::<Parent> { field_a: _, field_b: _, field_c } = partial_parent;
538    ///   });
539    ///
540    ///   insert(field_c);
541    /// }
542    /// ```
543    ///
544    /// [`forget`]: core::mem::forget
545    #[inline]
546    pub fn partial_move<R>(
547        self,
548        f: impl FnOnce(MovingPtr<'_, T, A>) -> R,
549    ) -> (MovingPtr<'a, MaybeUninit<T>, A>, R) {
550        let partial_ptr = self.0;
551        let ret = f(self);
552        (
553            MovingPtr(partial_ptr.cast::<MaybeUninit<T>>(), PhantomData),
554            ret,
555        )
556    }
557
558    /// Reads the value pointed to by this pointer.
559    #[inline]
560    pub fn read(self) -> T {
561        // SAFETY:
562        //  - `self.0` must be valid for reads as this type owns the value it points to.
563        //  - `self.0` must always point to a valid instance of type `T`
564        //  - If `A` is [`Aligned`], then `ptr` must be properly aligned for type `T`.
565        let value = unsafe { A::read_ptr(self.0.as_ptr()) };
566        mem::forget(self);
567        value
568    }
569
570    /// Writes the value pointed to by this pointer to a provided location.
571    ///
572    /// This does *not* drop the value stored at `dst` and it's the caller's responsibility
573    /// to ensure that it's properly dropped.
574    ///
575    /// # Safety
576    ///  - `dst` must be valid for writes.
577    ///  - If the `A` type parameter is [`Aligned`] then `dst` must be [properly aligned] for `T`.
578    ///  - The `dst` and the pointer `self` contains must not point at the same memory address.
579    ///
580    /// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
581    #[inline]
582    pub unsafe fn write_to(self, dst: *mut T) {
583        let src = self.0.as_ptr();
584        mem::forget(self);
585        // SAFETY:
586        //  - `src` must be valid for reads as this pointer is considered to own the value it points to.
587        //  - The caller is required to ensure that `dst` must be valid for writes.
588        //  - As `A` is `Aligned`, the caller is required to ensure that `dst` is aligned and `src` must
589        //    be aligned by the type's invariants.
590        //  - The caller is required to ensure that `dst` and `src` do not point to the same memory address.
591        //  - We took self by move and forgotten it, so nothing else can observe `src` being moved out.
592        unsafe { A::copy_nonoverlapping(src, dst, 1) };
593    }
594
595    /// Writes the value pointed to by this pointer into `dst`.
596    ///
597    /// The value previously stored at `dst` will be dropped.
598    ///
599    /// This has the same semantics as a normal `*dst = ...` assignment.
600    #[inline]
601    pub fn assign_to(self, dst: &mut T) {
602        // This code has the same semantics as the following:
603        // ```
604        // let src = self.0.as_ptr();
605        // mem::forget(self);
606        // *dst = unsafe { A::read(src) };
607        // ```
608        //
609        // However the above might codegen to multiple `memcpy`s, while the code below will avoid that.
610
611        struct DropGuard<'a, 'b, T, A: IsAligned> {
612            src: ManuallyDrop<MovingPtr<'a, T, A>>,
613            dst: &'b mut T,
614        }
615
616        impl<'a, 'b, T, A: IsAligned> Drop for DropGuard<'a, 'b, T, A> {
617            fn drop(&mut self) {
618                // SAFETY: `self.src` is always initialized with a valid `MovingPtr` and is only ever taken here
619                // in drop. No other code can observe the invalid `self.src` after this point.
620                let src = unsafe { ManuallyDrop::take(&mut self.src) };
621
622                // SAFETY:
623                // - `dst` is a mutable borrow, it must be valid for writes.
624                // - `dst` is a mutable borrow, it must always be aligned.
625                unsafe { src.write_to(self.dst) };
626            }
627        }
628
629        let guard = DropGuard {
630            src: ManuallyDrop::new(self),
631            dst,
632        };
633
634        // SAFETY:
635        // - `guard.dst` is a mutable borrow, it must point to a valid instance of `T`.
636        // - `guard.dst` is a mutable borrow, it must point to value that is valid for dropping.
637        // - `guard.dst` is a mutable borrow, it must not alias any other access.
638        // - `guard.dst` will be overwritten when `guard` is dropped, so no other code can observe it being dropped.
639        unsafe {
640            ptr::drop_in_place(guard.dst);
641        }
642    }
643
644    /// Creates a [`MovingPtr`] for a specific field within `self`.
645    ///
646    /// This function is explicitly made for deconstructive moves.
647    ///
648    /// The correct `byte_offset` for a field can be obtained via [`core::mem::offset_of`].
649    ///
650    /// # Safety
651    ///  - `f` must return a non-null pointer to a valid field inside `T`
652    ///  - If `A` is [`Aligned`], then `T` must not be `repr(packed)`
653    ///  - `self` should not be accessed or dropped as if it were a complete value after this function returns.
654    ///    Other fields that have not been moved out of may still be accessed or dropped separately.
655    ///  - This function cannot alias the field with any other access, including other calls to [`move_field`]
656    ///    for the same field, without first calling [`forget`] on it first.
657    ///
658    /// A result of the above invariants means that any operation that could cause `self` to be dropped while
659    /// the pointers to the fields are held will result in undefined behavior. This requires extra caution
660    /// around code that may panic. See the example below for an example of how to safely use this function.
661    ///
662    /// # Example
663    ///
664    /// ```
665    /// use core::mem::offset_of;
666    /// use bevy_ptr::{MovingPtr, move_as_ptr};
667    /// # struct FieldAType(usize);
668    /// # struct FieldBType(usize);
669    /// # struct FieldCType(usize);
670    /// # fn insert<T>(_ptr: MovingPtr<'_, T>) {}
671    ///
672    /// struct Parent {
673    ///   field_a: FieldAType,
674    ///   field_b: FieldBType,
675    ///   field_c: FieldCType,
676    /// }
677    ///
678    /// let parent = Parent {
679    ///    field_a: FieldAType(0),
680    ///    field_b: FieldBType(0),
681    ///    field_c: FieldCType(0),
682    /// };
683    ///
684    /// // Converts `parent` into a `MovingPtr`.
685    /// move_as_ptr!(parent);
686    ///
687    /// unsafe {
688    ///    let field_a = parent.move_field(|ptr| &raw mut (*ptr).field_a);
689    ///    let field_b = parent.move_field(|ptr| &raw mut (*ptr).field_b);
690    ///    let field_c = parent.move_field(|ptr| &raw mut (*ptr).field_c);
691    ///    // Each call to insert may panic! Ensure that `parent_ptr` cannot be dropped before
692    ///    // calling them!
693    ///    core::mem::forget(parent);
694    ///    insert(field_a);
695    ///    insert(field_b);
696    ///    insert(field_c);
697    /// }
698    /// ```
699    ///
700    /// [`forget`]: core::mem::forget
701    /// [`move_field`]: Self::move_field
702    #[inline(always)]
703    pub unsafe fn move_field<U>(&self, f: impl Fn(*mut T) -> *mut U) -> MovingPtr<'a, U, A> {
704        MovingPtr(
705            // SAFETY: The caller must ensure that `U` is the correct type for the field at `byte_offset`.
706            unsafe { NonNull::new_unchecked(f(self.0.as_ptr())) },
707            PhantomData,
708        )
709    }
710}
711
712impl<'a, T, A: IsAligned> MovingPtr<'a, MaybeUninit<T>, A> {
713    /// Creates a [`MovingPtr`] for a specific field within `self`.
714    ///
715    /// This function is explicitly made for deconstructive moves.
716    ///
717    /// The correct `byte_offset` for a field can be obtained via [`core::mem::offset_of`].
718    ///
719    /// # Safety
720    ///  - `f` must return a non-null pointer to a valid field inside `T`
721    ///  - If `A` is [`Aligned`], then `T` must not be `repr(packed)`
722    ///  - `self` should not be accessed or dropped as if it were a complete value after this function returns.
723    ///    Other fields that have not been moved out of may still be accessed or dropped separately.
724    ///  - This function cannot alias the field with any other access, including other calls to [`move_field`]
725    ///    for the same field, without first calling [`forget`] on it first.
726    ///
727    /// [`forget`]: core::mem::forget
728    /// [`move_field`]: Self::move_field
729    #[inline(always)]
730    pub unsafe fn move_maybe_uninit_field<U>(
731        &self,
732        f: impl Fn(*mut T) -> *mut U,
733    ) -> MovingPtr<'a, MaybeUninit<U>, A> {
734        let self_ptr = self.0.as_ptr().cast::<T>();
735        // SAFETY:
736        // - The caller must ensure that `U` is the correct type for the field at `byte_offset` and thus
737        //   cannot be null.
738        // - `MaybeUninit<T>` is `repr(transparent)` and thus must have the same memory layout as `T``
739        let field_ptr = unsafe { NonNull::new_unchecked(f(self_ptr)) };
740        MovingPtr(field_ptr.cast::<MaybeUninit<U>>(), PhantomData)
741    }
742}
743
744impl<'a, T, A: IsAligned> MovingPtr<'a, MaybeUninit<T>, A> {
745    /// Creates a [`MovingPtr`] pointing to a valid instance of `T`.
746    ///
747    /// See also: [`MaybeUninit::assume_init`].
748    ///
749    /// # Safety
750    /// It's up to the caller to ensure that the value pointed to by `self`
751    /// is really in an initialized state. Calling this when the content is not yet
752    /// fully initialized causes immediate undefined behavior.
753    #[inline]
754    pub unsafe fn assume_init(self) -> MovingPtr<'a, T, A> {
755        let value = MovingPtr(self.0.cast::<T>(), PhantomData);
756        mem::forget(self);
757        value
758    }
759}
760
761impl<T, A: IsAligned> Pointer for MovingPtr<'_, T, A> {
762    #[inline]
763    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
764        Pointer::fmt(&self.0, f)
765    }
766}
767
768impl<T> Debug for MovingPtr<'_, T, Aligned> {
769    #[inline]
770    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
771        write!(f, "MovingPtr<Aligned>({:?})", self.0)
772    }
773}
774
775impl<T> Debug for MovingPtr<'_, T, Unaligned> {
776    #[inline]
777    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
778        write!(f, "MovingPtr<Unaligned>({:?})", self.0)
779    }
780}
781
782impl<'a, T, A: IsAligned> From<MovingPtr<'a, T, A>> for OwningPtr<'a, A> {
783    #[inline]
784    fn from(value: MovingPtr<'a, T, A>) -> Self {
785        // SAFETY:
786        // - `value.0` must always point to valid value of type `T`.
787        // - The type parameter `A` is mirrored from input to output, keeping the same alignment guarantees.
788        // - `value.0` by construction must have correct provenance to allow read and writes of type `T`.
789        // - The lifetime `'a` is mirrored from input to output, keeping the same lifetime guarantees.
790        // - `OwningPtr` maintains the same aliasing invariants as `MovingPtr`.
791        let ptr = unsafe { OwningPtr::new(value.0.cast::<u8>()) };
792        mem::forget(value);
793        ptr
794    }
795}
796
797impl<'a, T> TryFrom<MovingPtr<'a, T, Unaligned>> for MovingPtr<'a, T, Aligned> {
798    type Error = MovingPtr<'a, T, Unaligned>;
799    #[inline]
800    fn try_from(value: MovingPtr<'a, T, Unaligned>) -> Result<Self, Self::Error> {
801        let ptr = value.0;
802        if ptr.as_ptr().is_aligned() {
803            mem::forget(value);
804            Ok(MovingPtr(ptr, PhantomData))
805        } else {
806            Err(value)
807        }
808    }
809}
810
811impl<T> Deref for MovingPtr<'_, T, Aligned> {
812    type Target = T;
813    #[inline]
814    fn deref(&self) -> &Self::Target {
815        let ptr = self.0.as_ptr().debug_ensure_aligned();
816        // SAFETY: This type owns the value it points to and the generic type parameter is `A` so this pointer must be aligned.
817        unsafe { &*ptr }
818    }
819}
820
821impl<T> DerefMut for MovingPtr<'_, T, Aligned> {
822    #[inline]
823    fn deref_mut(&mut self) -> &mut Self::Target {
824        let ptr = self.0.as_ptr().debug_ensure_aligned();
825        // SAFETY: This type owns the value it points to and the generic type parameter is `A` so this pointer must be aligned.
826        unsafe { &mut *ptr }
827    }
828}
829
830impl<T, A: IsAligned> Drop for MovingPtr<'_, T, A> {
831    fn drop(&mut self) {
832        // SAFETY:
833        //  - `self.0` must be valid for reads and writes as this pointer type owns the value it points to.
834        //  - `self.0` must always point to a valid instance of type `T`
835        //  - If `A` is `Aligned`, then `ptr` must be properly aligned for type `T` by construction.
836        //  - `self.0` owns the value it points to so it must always be valid for dropping until this pointer is dropped.
837        //  - This type owns the value it points to, so it's required to not mutably alias value that it points to.
838        unsafe { A::drop_in_place(self.0.as_ptr()) };
839    }
840}
841
842impl<'a, A: IsAligned> Ptr<'a, A> {
843    /// Creates a new instance from a raw pointer.
844    ///
845    /// # Safety
846    /// - `inner` must point to valid value of whatever the pointee type is.
847    /// - If the `A` type parameter is [`Aligned`] then `inner` must be [properly aligned] for the pointee type.
848    /// - `inner` must have correct provenance to allow reads of the pointee type.
849    /// - The lifetime `'a` must be constrained such that this [`Ptr`] will stay valid and nothing
850    ///   can mutate the pointee while this [`Ptr`] is live except through an [`UnsafeCell`].
851    ///
852    /// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
853    #[inline]
854    pub unsafe fn new(inner: NonNull<u8>) -> Self {
855        Self(inner, PhantomData)
856    }
857
858    /// Transforms this [`Ptr`] into an [`PtrMut`]
859    ///
860    /// # Safety
861    /// * The data pointed to by this `Ptr` must be valid for writes.
862    /// * There must be no active references (mutable or otherwise) to the data underlying this `Ptr`.
863    /// * Another [`PtrMut`] for the same [`Ptr`] must not be created until the first is dropped.
864    #[inline]
865    pub unsafe fn assert_unique(self) -> PtrMut<'a, A> {
866        PtrMut(self.0, PhantomData)
867    }
868
869    /// Transforms this [`Ptr<T>`] into a `&T` with the same lifetime
870    ///
871    /// # Safety
872    /// - `T` must be the erased pointee type for this [`Ptr`].
873    /// - If the type parameter `A` is [`Unaligned`] then this pointer must be [properly aligned]
874    ///   for the pointee type `T`.
875    ///
876    /// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
877    #[inline]
878    pub unsafe fn deref<T>(self) -> &'a T {
879        let ptr = self.as_ptr().cast::<T>().debug_ensure_aligned();
880        // SAFETY: The caller ensures the pointee is of type `T` and the pointer can be dereferenced.
881        unsafe { &*ptr }
882    }
883
884    /// Gets the underlying pointer, erasing the associated lifetime.
885    ///
886    /// If possible, it is strongly encouraged to use [`deref`](Self::deref) over this function,
887    /// as it retains the lifetime.
888    #[inline]
889    pub fn as_ptr(self) -> *const u8 {
890        self.0.as_ptr().cast_const()
891    }
892}
893
894impl<'a, T: ?Sized> From<&'a T> for Ptr<'a> {
895    #[inline]
896    fn from(val: &'a T) -> Self {
897        // SAFETY: The returned pointer has the same lifetime as the passed reference.
898        // Access is immutable.
899        unsafe { Self::new(NonNull::from(val).cast()) }
900    }
901}
902
903impl<'a, A: IsAligned> PtrMut<'a, A> {
904    /// Creates a new instance from a raw pointer.
905    ///
906    /// # Safety
907    /// - `inner` must point to valid value of whatever the pointee type is.
908    /// - If the `A` type parameter is [`Aligned`] then `inner` must be [properly aligned] for the pointee type.
909    /// - `inner` must have correct provenance to allow read and writes of the pointee type.
910    /// - The lifetime `'a` must be constrained such that this [`PtrMut`] will stay valid and nothing
911    ///   else can read or mutate the pointee while this [`PtrMut`] is live.
912    ///
913    /// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
914    #[inline]
915    pub unsafe fn new(inner: NonNull<u8>) -> Self {
916        Self(inner, PhantomData)
917    }
918
919    /// Transforms this [`PtrMut`] into an [`OwningPtr`]
920    ///
921    /// # Safety
922    /// Must have right to drop or move out of [`PtrMut`].
923    #[inline]
924    pub unsafe fn promote(self) -> OwningPtr<'a, A> {
925        OwningPtr(self.0, PhantomData)
926    }
927
928    /// Transforms this [`PtrMut<T>`] into a `&mut T` with the same lifetime
929    ///
930    /// # Safety
931    /// - `T` must be the erased pointee type for this [`PtrMut`].
932    /// - If the type parameter `A` is [`Unaligned`] then this pointer must be [properly aligned]
933    ///   for the pointee type `T`.
934    ///
935    /// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
936    #[inline]
937    pub unsafe fn deref_mut<T>(self) -> &'a mut T {
938        let ptr = self.as_ptr().cast::<T>().debug_ensure_aligned();
939        // SAFETY: The caller ensures the pointee is of type `T` and the pointer can be dereferenced.
940        unsafe { &mut *ptr }
941    }
942
943    /// Gets the underlying pointer, erasing the associated lifetime.
944    ///
945    /// If possible, it is strongly encouraged to use [`deref_mut`](Self::deref_mut) over
946    /// this function, as it retains the lifetime.
947    #[inline]
948    pub fn as_ptr(&self) -> *mut u8 {
949        self.0.as_ptr()
950    }
951
952    /// Gets a [`PtrMut`] from this with a smaller lifetime.
953    #[inline]
954    pub fn reborrow(&mut self) -> PtrMut<'_, A> {
955        // SAFETY: the ptrmut we're borrowing from is assumed to be valid
956        unsafe { PtrMut::new(self.0) }
957    }
958
959    /// Gets an immutable reference from this mutable reference
960    #[inline]
961    pub fn as_ref(&self) -> Ptr<'_, A> {
962        // SAFETY: The `PtrMut` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees
963        unsafe { Ptr::new(self.0) }
964    }
965}
966
967impl<'a, T: ?Sized> From<&'a mut T> for PtrMut<'a> {
968    #[inline]
969    fn from(val: &'a mut T) -> Self {
970        // SAFETY: The returned pointer has the same lifetime as the passed reference.
971        // The reference is mutable, and thus will not alias.
972        unsafe { Self::new(NonNull::from(val).cast()) }
973    }
974}
975
976impl<'a> OwningPtr<'a> {
977    /// This exists mostly to reduce compile times;
978    /// code is only duplicated per type, rather than per function called.
979    ///
980    /// # Safety
981    ///
982    /// Safety constraints of [`PtrMut::promote`] must be upheld.
983    unsafe fn make_internal<T>(temp: &mut ManuallyDrop<T>) -> OwningPtr<'_> {
984        // SAFETY: The constraints of `promote` are upheld by caller.
985        unsafe { PtrMut::from(&mut *temp).promote() }
986    }
987
988    /// Consumes a value and creates an [`OwningPtr`] to it while ensuring a double drop does not happen.
989    #[inline]
990    pub fn make<T, F: FnOnce(OwningPtr<'_>) -> R, R>(val: T, f: F) -> R {
991        let mut val = ManuallyDrop::new(val);
992        // SAFETY: The value behind the pointer will not get dropped or observed later,
993        // so it's safe to promote it to an owning pointer.
994        f(unsafe { Self::make_internal(&mut val) })
995    }
996}
997
998impl<'a, A: IsAligned> OwningPtr<'a, A> {
999    /// Creates a new instance from a raw pointer.
1000    ///
1001    /// # Safety
1002    /// - `inner` must point to valid value of whatever the pointee type is.
1003    /// - If the `A` type parameter is [`Aligned`] then `inner` must be [properly aligned] for the pointee type.
1004    /// - `inner` must have correct provenance to allow read and writes of the pointee type.
1005    /// - The lifetime `'a` must be constrained such that this [`OwningPtr`] will stay valid and nothing
1006    ///   else can read or mutate the pointee while this [`OwningPtr`] is live.
1007    ///
1008    /// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
1009    #[inline]
1010    pub unsafe fn new(inner: NonNull<u8>) -> Self {
1011        Self(inner, PhantomData)
1012    }
1013
1014    /// Consumes the [`OwningPtr`] to obtain ownership of the underlying data of type `T`.
1015    ///
1016    /// # Safety
1017    /// - `T` must be the erased pointee type for this [`OwningPtr`].
1018    /// - If the type parameter `A` is [`Unaligned`] then this pointer must be [properly aligned]
1019    ///   for the pointee type `T`.
1020    ///
1021    /// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
1022    #[inline]
1023    pub unsafe fn read<T>(self) -> T {
1024        let ptr = self.as_ptr().cast::<T>().debug_ensure_aligned();
1025        // SAFETY: The caller ensure the pointee is of type `T` and uphold safety for `read`.
1026        unsafe { ptr.read() }
1027    }
1028
1029    /// Casts to a concrete type as a [`MovingPtr`].
1030    ///
1031    /// # Safety
1032    /// - `T` must be the erased pointee type for this [`OwningPtr`].
1033    #[inline]
1034    pub unsafe fn cast<T>(self) -> MovingPtr<'a, T, A> {
1035        MovingPtr(self.0.cast::<T>(), PhantomData)
1036    }
1037
1038    /// Consumes the [`OwningPtr`] to drop the underlying data of type `T`.
1039    ///
1040    /// # Safety
1041    /// - `T` must be the erased pointee type for this [`OwningPtr`].
1042    /// - If the type parameter `A` is [`Unaligned`] then this pointer must be [properly aligned]
1043    ///   for the pointee type `T`.
1044    ///
1045    /// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
1046    #[inline]
1047    pub unsafe fn drop_as<T>(self) {
1048        let ptr = self.as_ptr().cast::<T>().debug_ensure_aligned();
1049        // SAFETY: The caller ensure the pointee is of type `T` and uphold safety for `drop_in_place`.
1050        unsafe {
1051            ptr.drop_in_place();
1052        }
1053    }
1054
1055    /// Gets the underlying pointer, erasing the associated lifetime.
1056    ///
1057    /// If possible, it is strongly encouraged to use the other more type-safe functions
1058    /// over this function.
1059    #[inline]
1060    pub fn as_ptr(&self) -> *mut u8 {
1061        self.0.as_ptr()
1062    }
1063
1064    /// Gets an immutable pointer from this owned pointer.
1065    #[inline]
1066    pub fn as_ref(&self) -> Ptr<'_, A> {
1067        // SAFETY: The `Owning` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees
1068        unsafe { Ptr::new(self.0) }
1069    }
1070
1071    /// Gets a mutable pointer from this owned pointer.
1072    #[inline]
1073    pub fn as_mut(&mut self) -> PtrMut<'_, A> {
1074        // SAFETY: The `Owning` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees
1075        unsafe { PtrMut::new(self.0) }
1076    }
1077}
1078
1079impl<'a> OwningPtr<'a, Unaligned> {
1080    /// Consumes the [`OwningPtr`] to obtain ownership of the underlying data of type `T`.
1081    ///
1082    /// # Safety
1083    /// - `T` must be the erased pointee type for this [`OwningPtr`].
1084    pub unsafe fn read_unaligned<T>(self) -> T {
1085        let ptr = self.as_ptr().cast::<T>();
1086        // SAFETY: The caller ensure the pointee is of type `T` and uphold safety for `read_unaligned`.
1087        unsafe { ptr.read_unaligned() }
1088    }
1089}
1090
1091/// Conceptually equivalent to `&'a [T]` but with length information cut out for performance
1092/// reasons.
1093///
1094/// Because this type does not store the length of the slice, it is unable to do any sort of bounds
1095/// checking. As such, only [`Self::get_unchecked()`] is available for indexing into the slice,
1096/// where the user is responsible for checking the bounds.
1097///
1098/// When compiled in debug mode (`#[cfg(debug_assertion)]`), this type will store the length of the
1099/// slice and perform bounds checking in [`Self::get_unchecked()`].
1100///
1101/// # Example
1102///
1103/// ```
1104/// # use core::mem::size_of;
1105/// # use bevy_ptr::ThinSlicePtr;
1106/// #
1107/// let slice: &[u32] = &[2, 4, 8];
1108/// let thin_slice = ThinSlicePtr::from(slice);
1109///
1110/// assert_eq!(*unsafe { thin_slice.get_unchecked(0) }, 2);
1111/// assert_eq!(*unsafe { thin_slice.get_unchecked(1) }, 4);
1112/// assert_eq!(*unsafe { thin_slice.get_unchecked(2) }, 8);
1113/// ```
1114pub struct ThinSlicePtr<'a, T> {
1115    ptr: NonNull<T>,
1116    #[cfg(debug_assertions)]
1117    len: usize,
1118    _marker: PhantomData<&'a [T]>,
1119}
1120
1121impl<'a, T> ThinSlicePtr<'a, T> {
1122    /// Indexes the slice without performing bounds checks.
1123    ///
1124    /// # Safety
1125    ///
1126    /// `index` must be in-bounds.
1127    #[inline]
1128    pub unsafe fn get_unchecked(&self, index: usize) -> &'a T {
1129        // We cannot use `debug_assert!` here because `self.len` does not exist when not in debug
1130        // mode.
1131        #[cfg(debug_assertions)]
1132        assert!(index < self.len, "tried to index out-of-bounds of a slice");
1133
1134        // SAFETY: The caller guarantees `index` is in-bounds so that the resulting pointer is
1135        // valid to dereference.
1136        unsafe { &*self.ptr.add(index).as_ptr() }
1137    }
1138
1139    /// Returns a slice without performing bounds checks.
1140    ///
1141    /// # Safety
1142    ///
1143    /// - There must be no mutable aliases for the lifetime `'a` to the slice. to the slice.
1144    /// - `len` must be less than or equal to the length of the slice.
1145    pub unsafe fn as_slice_unchecked(&self, len: usize) -> &'a [T] {
1146        #[cfg(debug_assertions)]
1147        assert!(len <= self.len, "tried to create an out-of-bounds slice");
1148
1149        // SAFETY:
1150        // - The caller guarantees `len` is not greater than the length of the slice.
1151        // - The caller guarantees the aliasing rules.
1152        // - `self.ptr` is a valid pointer for the type `T`.
1153        // - `len` is valid hence `len * size_of::<T>()` is less than `isize::MAX`.
1154        unsafe { core::slice::from_raw_parts(self.ptr.as_ptr(), len) }
1155    }
1156
1157    /// Returns a subslice without performing bounds checks.
1158    ///
1159    /// # Safety
1160    ///
1161    /// - There must be no mutable aliases for the lifetime `'a` to the slice.
1162    /// - `range.start` and `range.end` must be less than or equal to the length of the slice.
1163    /// - `range.start` must be less than or equal to `range.end`.
1164    pub unsafe fn slice_unchecked(&self, range: Range<usize>) -> &'a [T] {
1165        // SAFETY: The caller guarantees that `range` is within range of the slice.
1166        unsafe {
1167            core::slice::from_raw_parts(self.ptr.as_ptr().add(range.start), range.end - range.start)
1168        }
1169    }
1170}
1171
1172impl<'a, T> ThinSlicePtr<'a, UnsafeCell<T>> {
1173    /// Returns a mutable reference of the slice
1174    ///
1175    /// # Safety
1176    ///
1177    /// - There must not be any aliases for the lifetime `'a` to the slice.
1178    /// - `len` must be less than or equal to the length of the slice.
1179    pub unsafe fn as_mut_slice_unchecked(&self, len: usize) -> &'a mut [T] {
1180        #[cfg(debug_assertions)]
1181        assert!(len <= self.len, "tried to create an out-of-bounds slice");
1182
1183        // SAFETY:
1184        // - The caller ensures no aliases exist and `len` is in-bounds.
1185        // - `self.ptr` is a valid pointer for the type `T`.
1186        // - `len` is valid hence `len * size_of::<T>()` is less than `isize::MAX`.
1187        unsafe { core::slice::from_raw_parts_mut(UnsafeCell::raw_get(self.ptr.as_ptr()), len) }
1188    }
1189
1190    /// Returns a mutable subslice of the slice.
1191    ///
1192    /// # Safety
1193    ///
1194    /// - There must not be any aliases for the lifetime `'a` to the slice.
1195    /// - `range.start` and `range.end` must be less than or equal to the length of the slice.
1196    /// - `range.start` must be less than or equal to `range.end`.
1197    pub unsafe fn slice_mut_unchecked(&self, range: Range<usize>) -> &'a mut [T] {
1198        // SAFETY: The caller guarantees that `range` is within range of the slice.
1199        unsafe {
1200            core::slice::from_raw_parts_mut(
1201                UnsafeCell::raw_get(self.ptr.as_ptr().add(range.start)),
1202                range.end - range.start,
1203            )
1204        }
1205    }
1206
1207    /// Returns a slice pointer to the underlying type `T`.
1208    pub fn cast(&self) -> ThinSlicePtr<'a, T> {
1209        ThinSlicePtr {
1210            // SAFETY: `self.ptr` is non null hence `UnsafeCell::raw_get` always returns a non null pointer
1211            ptr: unsafe { NonNull::new_unchecked(UnsafeCell::raw_get(self.ptr.as_ptr())) },
1212            #[cfg(debug_assertions)]
1213            len: self.len,
1214            _marker: PhantomData,
1215        }
1216    }
1217}
1218
1219impl<'a, T> Clone for ThinSlicePtr<'a, T> {
1220    fn clone(&self) -> Self {
1221        *self
1222    }
1223}
1224
1225impl<'a, T> Copy for ThinSlicePtr<'a, T> {}
1226
1227impl<'a, T> From<&'a [T]> for ThinSlicePtr<'a, T> {
1228    #[inline]
1229    fn from(slice: &'a [T]) -> Self {
1230        let ptr = slice.as_ptr().cast_mut().debug_ensure_aligned();
1231
1232        Self {
1233            // SAFETY: A reference can never be null.
1234            ptr: unsafe { NonNull::new_unchecked(ptr) },
1235            #[cfg(debug_assertions)]
1236            len: slice.len(),
1237            _marker: PhantomData,
1238        }
1239    }
1240}
1241
1242mod private {
1243    use core::cell::UnsafeCell;
1244
1245    pub trait SealedUnsafeCell {}
1246    impl<'a, T> SealedUnsafeCell for &'a UnsafeCell<T> {}
1247}
1248
1249/// Extension trait for helper methods on [`UnsafeCell`]
1250pub trait UnsafeCellDeref<'a, T>: private::SealedUnsafeCell {
1251    /// # Safety
1252    /// - The returned value must be unique and not alias any mutable or immutable references to the contents of the [`UnsafeCell`].
1253    /// - 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).
1254    unsafe fn deref_mut(self) -> &'a mut T;
1255
1256    /// # Safety
1257    /// - For the lifetime `'a` of the returned value you must not construct a mutable reference to the contents of the [`UnsafeCell`].
1258    /// - 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).
1259    unsafe fn deref(self) -> &'a T;
1260
1261    /// Returns a copy of the contained value.
1262    ///
1263    /// # Safety
1264    /// - The [`UnsafeCell`] must not currently have a mutable reference to its content.
1265    /// - 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).
1266    unsafe fn read(self) -> T
1267    where
1268        T: Copy;
1269}
1270
1271impl<'a, T> UnsafeCellDeref<'a, T> for &'a UnsafeCell<T> {
1272    #[inline]
1273    unsafe fn deref_mut(self) -> &'a mut T {
1274        // SAFETY: The caller upholds the alias rules.
1275        unsafe { &mut *self.get() }
1276    }
1277    #[inline]
1278    unsafe fn deref(self) -> &'a T {
1279        // SAFETY: The caller upholds the alias rules.
1280        unsafe { &*self.get() }
1281    }
1282
1283    #[inline]
1284    unsafe fn read(self) -> T
1285    where
1286        T: Copy,
1287    {
1288        // SAFETY: The caller upholds the alias rules.
1289        unsafe { self.get().read() }
1290    }
1291}
1292
1293trait DebugEnsureAligned {
1294    fn debug_ensure_aligned(self) -> Self;
1295}
1296
1297// Disable this for miri runs as it already checks if pointer to reference
1298// casts are properly aligned.
1299#[cfg(all(debug_assertions, not(miri)))]
1300impl<T: Sized> DebugEnsureAligned for *mut T {
1301    #[track_caller]
1302    fn debug_ensure_aligned(self) -> Self {
1303        assert!(
1304            self.is_aligned(),
1305            "pointer is not aligned. Address {:p} does not have alignment {} for type {}",
1306            self,
1307            align_of::<T>(),
1308            core::any::type_name::<T>()
1309        );
1310        self
1311    }
1312}
1313
1314#[cfg(any(not(debug_assertions), miri))]
1315impl<T: Sized> DebugEnsureAligned for *mut T {
1316    #[inline(always)]
1317    fn debug_ensure_aligned(self) -> Self {
1318        self
1319    }
1320}
1321
1322// Same as above, but for *const T.
1323#[cfg(all(debug_assertions, not(miri)))]
1324impl<T: Sized> DebugEnsureAligned for *const T {
1325    #[track_caller]
1326    fn debug_ensure_aligned(self) -> Self {
1327        // Call into the *mut version.
1328        self.cast_mut().debug_ensure_aligned();
1329        self
1330    }
1331}
1332
1333#[cfg(any(not(debug_assertions), miri))]
1334impl<T: Sized> DebugEnsureAligned for *const T {
1335    #[inline(always)]
1336    fn debug_ensure_aligned(self) -> Self {
1337        self
1338    }
1339}
1340
1341/// Safely converts a owned value into a [`MovingPtr`] while minimizing the number of stack copies.
1342///
1343/// This cannot be used as expression and must be used as a statement. Internally this macro works via variable shadowing.
1344#[macro_export]
1345macro_rules! move_as_ptr {
1346    ($value: ident) => {
1347        let mut $value = ::core::mem::MaybeUninit::new($value);
1348        // SAFETY:
1349        // - This macro shadows a MaybeUninit value that took ownership of the original value.
1350        //   it is impossible to refer to the original value, preventing further access after
1351        //   the `MovingPtr` has been used. `MaybeUninit` also prevents the compiler from
1352        //   dropping the original value.
1353        let $value = unsafe { $crate::MovingPtr::from_value(&mut $value) };
1354    };
1355}
1356
1357/// Helper macro used by [`deconstruct_moving_ptr`] to extract
1358/// the pattern from `field: pattern` or `field` shorthand.
1359#[macro_export]
1360#[doc(hidden)]
1361macro_rules! get_pattern {
1362    ($field_index:tt) => {
1363        $field_index
1364    };
1365    ($field_index:tt: $pattern:pat) => {
1366        $pattern
1367    };
1368}
1369
1370/// Deconstructs a [`MovingPtr`] into its individual fields.
1371///
1372/// This consumes the [`MovingPtr`] and hands out [`MovingPtr`] wrappers around
1373/// pointers to each of its fields. The value will *not* be dropped.
1374///
1375/// The macro should wrap a `let` expression with a struct pattern.
1376/// It does not support matching tuples by position,
1377/// so for tuple structs you should use `0: pat` syntax.
1378///
1379/// For tuples themselves, pass the identifier `tuple` instead of the struct name,
1380/// like `let tuple { 0: pat0, 1: pat1 } = value`.
1381///
1382/// This can also project into `MaybeUninit`.
1383/// Wrap the type name or `tuple` with `MaybeUninit::<_>`,
1384/// and the macro will deconstruct a `MovingPtr<MaybeUninit<ParentType>>`
1385/// into `MovingPtr<MaybeUninit<FieldType>>` values.
1386///
1387/// # Examples
1388///
1389/// ## Structs
1390///
1391/// ```
1392/// use core::mem::{offset_of, MaybeUninit};
1393/// use bevy_ptr::{MovingPtr, move_as_ptr};
1394/// # use bevy_ptr::Unaligned;
1395/// # struct FieldAType(usize);
1396/// # struct FieldBType(usize);
1397/// # struct FieldCType(usize);
1398///
1399/// # pub struct Parent {
1400/// #  pub field_a: FieldAType,
1401/// #  pub field_b: FieldBType,
1402/// #  pub field_c: FieldCType,
1403/// # }
1404///
1405/// let parent = Parent {
1406///   field_a: FieldAType(11),
1407///   field_b: FieldBType(22),
1408///   field_c: FieldCType(33),
1409/// };
1410///
1411/// let mut target_a = FieldAType(101);
1412/// let mut target_b = FieldBType(102);
1413/// let mut target_c = FieldCType(103);
1414///
1415/// // Converts `parent` into a `MovingPtr`
1416/// move_as_ptr!(parent);
1417///
1418/// // The field names must match the name used in the type definition.
1419/// // Each one will be a `MovingPtr` of the field's type.
1420/// bevy_ptr::deconstruct_moving_ptr!({
1421///   let Parent { field_a, field_b, field_c } = parent;
1422/// });
1423///
1424/// field_a.assign_to(&mut target_a);
1425/// field_b.assign_to(&mut target_b);
1426/// field_c.assign_to(&mut target_c);
1427///
1428/// assert_eq!(target_a.0, 11);
1429/// assert_eq!(target_b.0, 22);
1430/// assert_eq!(target_c.0, 33);
1431/// ```
1432///
1433/// ## Tuples
1434///
1435/// ```
1436/// use core::mem::{offset_of, MaybeUninit};
1437/// use bevy_ptr::{MovingPtr, move_as_ptr};
1438/// # use bevy_ptr::Unaligned;
1439/// # struct FieldAType(usize);
1440/// # struct FieldBType(usize);
1441/// # struct FieldCType(usize);
1442///
1443/// # pub struct Parent {
1444/// #   pub field_a: FieldAType,
1445/// #  pub field_b: FieldBType,
1446/// #  pub field_c: FieldCType,
1447/// # }
1448///
1449/// let parent = (
1450///   FieldAType(11),
1451///   FieldBType(22),
1452///   FieldCType(33),
1453/// );
1454///
1455/// let mut target_a = FieldAType(101);
1456/// let mut target_b = FieldBType(102);
1457/// let mut target_c = FieldCType(103);
1458///
1459/// // Converts `parent` into a `MovingPtr`
1460/// move_as_ptr!(parent);
1461///
1462/// // The field names must match the name used in the type definition.
1463/// // Each one will be a `MovingPtr` of the field's type.
1464/// bevy_ptr::deconstruct_moving_ptr!({
1465///   let tuple { 0: field_a, 1: field_b, 2: field_c } = parent;
1466/// });
1467///
1468/// field_a.assign_to(&mut target_a);
1469/// field_b.assign_to(&mut target_b);
1470/// field_c.assign_to(&mut target_c);
1471///
1472/// assert_eq!(target_a.0, 11);
1473/// assert_eq!(target_b.0, 22);
1474/// assert_eq!(target_c.0, 33);
1475/// ```
1476///
1477/// ## `MaybeUninit`
1478///
1479/// ```
1480/// use core::mem::{offset_of, MaybeUninit};
1481/// use bevy_ptr::{MovingPtr, move_as_ptr};
1482/// # use bevy_ptr::Unaligned;
1483/// # struct FieldAType(usize);
1484/// # struct FieldBType(usize);
1485/// # struct FieldCType(usize);
1486///
1487/// # pub struct Parent {
1488/// #  pub field_a: FieldAType,
1489/// #  pub field_b: FieldBType,
1490/// #  pub field_c: FieldCType,
1491/// # }
1492///
1493/// let parent = MaybeUninit::new(Parent {
1494///   field_a: FieldAType(11),
1495///   field_b: FieldBType(22),
1496///   field_c: FieldCType(33),
1497/// });
1498///
1499/// let mut target_a = MaybeUninit::new(FieldAType(101));
1500/// let mut target_b = MaybeUninit::new(FieldBType(102));
1501/// let mut target_c = MaybeUninit::new(FieldCType(103));
1502///
1503/// // Converts `parent` into a `MovingPtr`
1504/// move_as_ptr!(parent);
1505///
1506/// // The field names must match the name used in the type definition.
1507/// // Each one will be a `MovingPtr` of the field's type.
1508/// bevy_ptr::deconstruct_moving_ptr!({
1509///   let MaybeUninit::<Parent> { field_a, field_b, field_c } = parent;
1510/// });
1511///
1512/// field_a.assign_to(&mut target_a);
1513/// field_b.assign_to(&mut target_b);
1514/// field_c.assign_to(&mut target_c);
1515///
1516/// unsafe {
1517///   assert_eq!(target_a.assume_init().0, 11);
1518///   assert_eq!(target_b.assume_init().0, 22);
1519///   assert_eq!(target_c.assume_init().0, 33);
1520/// }
1521/// ```
1522///
1523/// [`assign_to`]: MovingPtr::assign_to
1524#[macro_export]
1525macro_rules! deconstruct_moving_ptr {
1526    ({ let tuple { $($field_index:tt: $pattern:pat),* $(,)? } = $ptr:expr ;}) => {
1527        // Specify the type to make sure the `mem::forget` doesn't forget a mere `&mut MovingPtr`
1528        let mut ptr: $crate::MovingPtr<_, _> = $ptr;
1529        let _ = || {
1530            let value = &mut *ptr;
1531            // Ensure that each field index exists and is mentioned only once
1532            // Ensure that the struct is not `repr(packed)` and that we may take references to fields
1533            ::core::hint::black_box(($(&mut value.$field_index,)*));
1534            // Ensure that `ptr` is a tuple and not something that derefs to it
1535            // Ensure that the number of patterns matches the number of fields
1536            fn unreachable<T>(_index: usize) -> T {
1537                ::core::unreachable!()
1538            }
1539            *value = ($(unreachable($field_index),)*);
1540        };
1541        // SAFETY:
1542        // - `f` does a raw pointer offset, which always returns a non-null pointer to a field inside `T`
1543        // - The struct is not `repr(packed)`, since otherwise the block of code above would fail compilation
1544        // - `mem::forget` is called on `self` immediately after these calls
1545        // - Each field is distinct, since otherwise the block of code above would fail compilation
1546        $(let $pattern = unsafe { ptr.move_field(|f| &raw mut (*f).$field_index) };)*
1547        #[expect(clippy::mem_forget, reason = "`deconstruct_moving_ptr` needs to forget the `MovingPtr` due to its safety requirements.")]
1548        ::core::mem::forget(ptr);
1549    };
1550    ({ let MaybeUninit::<tuple> { $($field_index:tt: $pattern:pat),* $(,)? } = $ptr:expr ;}) => {
1551        // Specify the type to make sure the `mem::forget` doesn't forget a mere `&mut MovingPtr`
1552        let mut ptr: $crate::MovingPtr<::core::mem::MaybeUninit<_>, _> = $ptr;
1553        let _ = || {
1554            // SAFETY: This closure is never called
1555            let value = unsafe { ptr.assume_init_mut() };
1556            // Ensure that each field index exists and is mentioned only once
1557            // Ensure that the struct is not `repr(packed)` and that we may take references to fields
1558            ::core::hint::black_box(($(&mut value.$field_index,)*));
1559            // Ensure that `ptr` is a tuple and not something that derefs to it
1560            // Ensure that the number of patterns matches the number of fields
1561            fn unreachable<T>(_index: usize) -> T {
1562                ::core::unreachable!()
1563            }
1564            *value = ($(unreachable($field_index),)*);
1565        };
1566        // SAFETY:
1567        // - `f` does a raw pointer offset, which always returns a non-null pointer to a field inside `T`
1568        // - The struct is not `repr(packed)`, since otherwise the block of code above would fail compilation
1569        // - `mem::forget` is called on `self` immediately after these calls
1570        // - Each field is distinct, since otherwise the block of code above would fail compilation
1571        $(let $pattern = unsafe { ptr.move_maybe_uninit_field(|f| &raw mut (*f).$field_index) };)*
1572        #[expect(clippy::mem_forget, reason = "`deconstruct_moving_ptr` needs to forget the `MovingPtr` due to its safety requirements.")]
1573        ::core::mem::forget(ptr);
1574    };
1575    ({ let $struct_name:ident { $($field_index:tt$(: $pattern:pat)?),* $(,)? } = $ptr:expr ;}) => {
1576        // Specify the type to make sure the `mem::forget` doesn't forget a mere `&mut MovingPtr`
1577        let mut ptr: $crate::MovingPtr<_, _> = $ptr;
1578        let _ = || {
1579            let value = &mut *ptr;
1580            // Ensure that each field index exists is mentioned only once
1581            // Ensure that each field is on the struct and not accessed using autoref
1582            let $struct_name { $($field_index: _),* } = value;
1583            // Ensure that the struct is not `repr(packed)` and that we may take references to fields
1584            ::core::hint::black_box(($(&mut value.$field_index),*));
1585            // Ensure that `ptr` is a `$struct_name` and not just something that derefs to it
1586            let value: *mut _ = value;
1587            // SAFETY: This closure is never called
1588            $struct_name { ..unsafe { value.read() } };
1589        };
1590        // SAFETY:
1591        // - `f` does a raw pointer offset, which always returns a non-null pointer to a field inside `T`
1592        // - The struct is not `repr(packed)`, since otherwise the block of code above would fail compilation
1593        // - `mem::forget` is called on `self` immediately after these calls
1594        // - Each field is distinct, since otherwise the block of code above would fail compilation
1595        $(let $crate::get_pattern!($field_index$(: $pattern)?) = unsafe { ptr.move_field(|f| &raw mut (*f).$field_index) };)*
1596        #[expect(clippy::mem_forget, reason = "`deconstruct_moving_ptr` needs to forget the `MovingPtr` due to its safety requirements.")]
1597        ::core::mem::forget(ptr);
1598    };
1599    ({ let MaybeUninit::<$struct_name:ident> { $($field_index:tt$(: $pattern:pat)?),* $(,)? } = $ptr:expr ;}) => {
1600        // Specify the type to make sure the `mem::forget` doesn't forget a mere `&mut MovingPtr`
1601        let mut ptr: $crate::MovingPtr<::core::mem::MaybeUninit<_>, _> = $ptr;
1602        let _ = || {
1603            // SAFETY: This closure is never called
1604            let value = unsafe { ptr.assume_init_mut() };
1605            // Ensure that each field index exists is mentioned only once
1606            // Ensure that each field is on the struct and not accessed using autoref
1607            let $struct_name { $($field_index: _),* } = value;
1608            // Ensure that the struct is not `repr(packed)` and that we may take references to fields
1609            ::core::hint::black_box(($(&mut value.$field_index),*));
1610            // Ensure that `ptr` is a `$struct_name` and not just something that derefs to it
1611            let value: *mut _ = value;
1612            // SAFETY: This closure is never called
1613            $struct_name { ..unsafe { value.read() } };
1614        };
1615        // SAFETY:
1616        // - `f` does a raw pointer offset, which always returns a non-null pointer to a field inside `T`
1617        // - The struct is not `repr(packed)`, since otherwise the block of code above would fail compilation
1618        // - `mem::forget` is called on `self` immediately after these calls
1619        // - Each field is distinct, since otherwise the block of code above would fail compilation
1620        $(let $crate::get_pattern!($field_index$(: $pattern)?) = unsafe { ptr.move_maybe_uninit_field(|f| &raw mut (*f).$field_index) };)*
1621        #[expect(clippy::mem_forget, reason = "`deconstruct_moving_ptr` needs to forget the `MovingPtr` due to its safety requirements.")]
1622        ::core::mem::forget(ptr);
1623    };
1624}