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},
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 module 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 module 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.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.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 ///
579 /// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
580 #[inline]
581 pub unsafe fn write_to(self, dst: *mut T) {
582 let src = self.0.as_ptr();
583 mem::forget(self);
584 // SAFETY:
585 // - `src` must be valid for reads as this pointer is considered to own the value it points to.
586 // - The caller is required to ensure that `dst` must be valid for writes.
587 // - As `A` is `Aligned`, the caller is required to ensure that `dst` is aligned and `src` must
588 // be aligned by the type's invariants.
589 unsafe { A::copy_nonoverlapping(src, dst, 1) };
590 }
591
592 /// Writes the value pointed to by this pointer into `dst`.
593 ///
594 /// The value previously stored at `dst` will be dropped.
595 #[inline]
596 pub fn assign_to(self, dst: &mut T) {
597 // SAFETY:
598 // - `dst` is a mutable borrow, it must point to a valid instance of `T`.
599 // - `dst` is a mutable borrow, it must point to value that is valid for dropping.
600 // - `dst` is a mutable borrow, it must not alias any other access.
601 unsafe {
602 ptr::drop_in_place(dst);
603 }
604 // SAFETY:
605 // - `dst` is a mutable borrow, it must be valid for writes.
606 // - `dst` is a mutable borrow, it must always be aligned.
607 unsafe {
608 self.write_to(dst);
609 }
610 }
611
612 /// Creates a [`MovingPtr`] for a specific field within `self`.
613 ///
614 /// This function is explicitly made for deconstructive moves.
615 ///
616 /// The correct `byte_offset` for a field can be obtained via [`core::mem::offset_of`].
617 ///
618 /// # Safety
619 /// - `f` must return a non-null pointer to a valid field inside `T`
620 /// - If `A` is [`Aligned`], then `T` must not be `repr(packed)`
621 /// - `self` should not be accessed or dropped as if it were a complete value after this function returns.
622 /// Other fields that have not been moved out of may still be accessed or dropped separately.
623 /// - This function cannot alias the field with any other access, including other calls to [`move_field`]
624 /// for the same field, without first calling [`forget`] on it first.
625 ///
626 /// A result of the above invariants means that any operation that could cause `self` to be dropped while
627 /// the pointers to the fields are held will result in undefined behavior. This requires extra caution
628 /// around code that may panic. See the example below for an example of how to safely use this function.
629 ///
630 /// # Example
631 ///
632 /// ```
633 /// use core::mem::offset_of;
634 /// use bevy_ptr::{MovingPtr, move_as_ptr};
635 /// # struct FieldAType(usize);
636 /// # struct FieldBType(usize);
637 /// # struct FieldCType(usize);
638 /// # fn insert<T>(_ptr: MovingPtr<'_, T>) {}
639 ///
640 /// struct Parent {
641 /// field_a: FieldAType,
642 /// field_b: FieldBType,
643 /// field_c: FieldCType,
644 /// }
645 ///
646 /// let parent = Parent {
647 /// field_a: FieldAType(0),
648 /// field_b: FieldBType(0),
649 /// field_c: FieldCType(0),
650 /// };
651 ///
652 /// // Converts `parent` into a `MovingPtr`.
653 /// move_as_ptr!(parent);
654 ///
655 /// unsafe {
656 /// let field_a = parent.move_field(|ptr| &raw mut (*ptr).field_a);
657 /// let field_b = parent.move_field(|ptr| &raw mut (*ptr).field_b);
658 /// let field_c = parent.move_field(|ptr| &raw mut (*ptr).field_c);
659 /// // Each call to insert may panic! Ensure that `parent_ptr` cannot be dropped before
660 /// // calling them!
661 /// core::mem::forget(parent);
662 /// insert(field_a);
663 /// insert(field_b);
664 /// insert(field_c);
665 /// }
666 /// ```
667 ///
668 /// [`forget`]: core::mem::forget
669 /// [`move_field`]: Self::move_field
670 #[inline(always)]
671 pub unsafe fn move_field<U>(&self, f: impl Fn(*mut T) -> *mut U) -> MovingPtr<'a, U, A> {
672 MovingPtr(
673 // SAFETY: The caller must ensure that `U` is the correct type for the field at `byte_offset`.
674 unsafe { NonNull::new_unchecked(f(self.0.as_ptr())) },
675 PhantomData,
676 )
677 }
678}
679
680impl<'a, T, A: IsAligned> MovingPtr<'a, MaybeUninit<T>, A> {
681 /// Creates a [`MovingPtr`] for a specific field within `self`.
682 ///
683 /// This function is explicitly made for deconstructive moves.
684 ///
685 /// The correct `byte_offset` for a field can be obtained via [`core::mem::offset_of`].
686 ///
687 /// # Safety
688 /// - `f` must return a non-null pointer to a valid field inside `T`
689 /// - If `A` is [`Aligned`], then `T` must not be `repr(packed)`
690 /// - `self` should not be accessed or dropped as if it were a complete value after this function returns.
691 /// Other fields that have not been moved out of may still be accessed or dropped separately.
692 /// - This function cannot alias the field with any other access, including other calls to [`move_field`]
693 /// for the same field, without first calling [`forget`] on it first.
694 ///
695 /// [`forget`]: core::mem::forget
696 /// [`move_field`]: Self::move_field
697 #[inline(always)]
698 pub unsafe fn move_maybe_uninit_field<U>(
699 &self,
700 f: impl Fn(*mut T) -> *mut U,
701 ) -> MovingPtr<'a, MaybeUninit<U>, A> {
702 let self_ptr = self.0.as_ptr().cast::<T>();
703 // SAFETY:
704 // - The caller must ensure that `U` is the correct type for the field at `byte_offset` and thus
705 // cannot be null.
706 // - `MaybeUninit<T>` is `repr(transparent)` and thus must have the same memory layout as `T``
707 let field_ptr = unsafe { NonNull::new_unchecked(f(self_ptr)) };
708 MovingPtr(field_ptr.cast::<MaybeUninit<U>>(), PhantomData)
709 }
710}
711
712impl<'a, T, A: IsAligned> MovingPtr<'a, MaybeUninit<T>, A> {
713 /// Creates a [`MovingPtr`] pointing to a valid instance of `T`.
714 ///
715 /// See also: [`MaybeUninit::assume_init`].
716 ///
717 /// # Safety
718 /// It's up to the caller to ensure that the value pointed to by `self`
719 /// is really in an initialized state. Calling this when the content is not yet
720 /// fully initialized causes immediate undefined behavior.
721 #[inline]
722 pub unsafe fn assume_init(self) -> MovingPtr<'a, T, A> {
723 let value = MovingPtr(self.0.cast::<T>(), PhantomData);
724 mem::forget(self);
725 value
726 }
727}
728
729impl<T, A: IsAligned> Pointer for MovingPtr<'_, T, A> {
730 #[inline]
731 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
732 Pointer::fmt(&self.0, f)
733 }
734}
735
736impl<T> Debug for MovingPtr<'_, T, Aligned> {
737 #[inline]
738 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
739 write!(f, "MovingPtr<Aligned>({:?})", self.0)
740 }
741}
742
743impl<T> Debug for MovingPtr<'_, T, Unaligned> {
744 #[inline]
745 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
746 write!(f, "MovingPtr<Unaligned>({:?})", self.0)
747 }
748}
749
750impl<'a, T, A: IsAligned> From<MovingPtr<'a, T, A>> for OwningPtr<'a, A> {
751 #[inline]
752 fn from(value: MovingPtr<'a, T, A>) -> Self {
753 // SAFETY:
754 // - `value.0` must always point to valid value of type `T`.
755 // - The type parameter `A` is mirrored from input to output, keeping the same alignment guarantees.
756 // - `value.0` by construction must have correct provenance to allow read and writes of type `T`.
757 // - The lifetime `'a` is mirrored from input to output, keeping the same lifetime guarantees.
758 // - `OwningPtr` maintains the same aliasing invariants as `MovingPtr`.
759 let ptr = unsafe { OwningPtr::new(value.0.cast::<u8>()) };
760 mem::forget(value);
761 ptr
762 }
763}
764
765impl<'a, T> TryFrom<MovingPtr<'a, T, Unaligned>> for MovingPtr<'a, T, Aligned> {
766 type Error = MovingPtr<'a, T, Unaligned>;
767 #[inline]
768 fn try_from(value: MovingPtr<'a, T, Unaligned>) -> Result<Self, Self::Error> {
769 let ptr = value.0;
770 if ptr.as_ptr().is_aligned() {
771 mem::forget(value);
772 Ok(MovingPtr(ptr, PhantomData))
773 } else {
774 Err(value)
775 }
776 }
777}
778
779impl<T> Deref for MovingPtr<'_, T, Aligned> {
780 type Target = T;
781 #[inline]
782 fn deref(&self) -> &Self::Target {
783 let ptr = self.0.as_ptr().debug_ensure_aligned();
784 // SAFETY: This type owns the value it points to and the generic type parameter is `A` so this pointer must be aligned.
785 unsafe { &*ptr }
786 }
787}
788
789impl<T> DerefMut for MovingPtr<'_, T, Aligned> {
790 #[inline]
791 fn deref_mut(&mut self) -> &mut Self::Target {
792 let ptr = self.0.as_ptr().debug_ensure_aligned();
793 // SAFETY: This type owns the value it points to and the generic type parameter is `A` so this pointer must be aligned.
794 unsafe { &mut *ptr }
795 }
796}
797
798impl<T, A: IsAligned> Drop for MovingPtr<'_, T, A> {
799 fn drop(&mut self) {
800 // SAFETY:
801 // - `self.0` must be valid for reads and writes as this pointer type owns the value it points to.
802 // - `self.0` must always point to a valid instance of type `T`
803 // - If `A` is `Aligned`, then `ptr` must be properly aligned for type `T` by construction.
804 // - `self.0` owns the value it points to so it must always be valid for dropping until this pointer is dropped.
805 // - This type owns the value it points to, so it's required to not mutably alias value that it points to.
806 unsafe { A::drop_in_place(self.0.as_ptr()) };
807 }
808}
809
810impl<'a, A: IsAligned> Ptr<'a, A> {
811 /// Creates a new instance from a raw pointer.
812 ///
813 /// # Safety
814 /// - `inner` must point to valid value of whatever the pointee type is.
815 /// - If the `A` type parameter is [`Aligned`] then `inner` must be [properly aligned] for the pointee type.
816 /// - `inner` must have correct provenance to allow reads of the pointee type.
817 /// - The lifetime `'a` must be constrained such that this [`Ptr`] will stay valid and nothing
818 /// can mutate the pointee while this [`Ptr`] is live except through an [`UnsafeCell`].
819 ///
820 /// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
821 #[inline]
822 pub unsafe fn new(inner: NonNull<u8>) -> Self {
823 Self(inner, PhantomData)
824 }
825
826 /// Transforms this [`Ptr`] into an [`PtrMut`]
827 ///
828 /// # Safety
829 /// * The data pointed to by this `Ptr` must be valid for writes.
830 /// * There must be no active references (mutable or otherwise) to the data underlying this `Ptr`.
831 /// * Another [`PtrMut`] for the same [`Ptr`] must not be created until the first is dropped.
832 #[inline]
833 pub unsafe fn assert_unique(self) -> PtrMut<'a, A> {
834 PtrMut(self.0, PhantomData)
835 }
836
837 /// Transforms this [`Ptr<T>`] into a `&T` with the same lifetime
838 ///
839 /// # Safety
840 /// - `T` must be the erased pointee type for this [`Ptr`].
841 /// - If the type parameter `A` is [`Unaligned`] then this pointer must be [properly aligned]
842 /// for the pointee type `T`.
843 ///
844 /// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
845 #[inline]
846 pub unsafe fn deref<T>(self) -> &'a T {
847 let ptr = self.as_ptr().cast::<T>().debug_ensure_aligned();
848 // SAFETY: The caller ensures the pointee is of type `T` and the pointer can be dereferenced.
849 unsafe { &*ptr }
850 }
851
852 /// Gets the underlying pointer, erasing the associated lifetime.
853 ///
854 /// If possible, it is strongly encouraged to use [`deref`](Self::deref) over this function,
855 /// as it retains the lifetime.
856 #[inline]
857 pub fn as_ptr(self) -> *mut u8 {
858 self.0.as_ptr()
859 }
860}
861
862impl<'a, T: ?Sized> From<&'a T> for Ptr<'a> {
863 #[inline]
864 fn from(val: &'a T) -> Self {
865 // SAFETY: The returned pointer has the same lifetime as the passed reference.
866 // Access is immutable.
867 unsafe { Self::new(NonNull::from(val).cast()) }
868 }
869}
870
871impl<'a, A: IsAligned> PtrMut<'a, A> {
872 /// Creates a new instance from a raw pointer.
873 ///
874 /// # Safety
875 /// - `inner` must point to valid value of whatever the pointee type is.
876 /// - If the `A` type parameter is [`Aligned`] then `inner` must be [properly aligned] for the pointee type.
877 /// - `inner` must have correct provenance to allow read and writes of the pointee type.
878 /// - The lifetime `'a` must be constrained such that this [`PtrMut`] will stay valid and nothing
879 /// else can read or mutate the pointee while this [`PtrMut`] is live.
880 ///
881 /// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
882 #[inline]
883 pub unsafe fn new(inner: NonNull<u8>) -> Self {
884 Self(inner, PhantomData)
885 }
886
887 /// Transforms this [`PtrMut`] into an [`OwningPtr`]
888 ///
889 /// # Safety
890 /// Must have right to drop or move out of [`PtrMut`].
891 #[inline]
892 pub unsafe fn promote(self) -> OwningPtr<'a, A> {
893 OwningPtr(self.0, PhantomData)
894 }
895
896 /// Transforms this [`PtrMut<T>`] into a `&mut T` with the same lifetime
897 ///
898 /// # Safety
899 /// - `T` must be the erased pointee type for this [`PtrMut`].
900 /// - If the type parameter `A` is [`Unaligned`] then this pointer must be [properly aligned]
901 /// for the pointee type `T`.
902 ///
903 /// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
904 #[inline]
905 pub unsafe fn deref_mut<T>(self) -> &'a mut T {
906 let ptr = self.as_ptr().cast::<T>().debug_ensure_aligned();
907 // SAFETY: The caller ensures the pointee is of type `T` and the pointer can be dereferenced.
908 unsafe { &mut *ptr }
909 }
910
911 /// Gets the underlying pointer, erasing the associated lifetime.
912 ///
913 /// If possible, it is strongly encouraged to use [`deref_mut`](Self::deref_mut) over
914 /// this function, as it retains the lifetime.
915 #[inline]
916 pub fn as_ptr(&self) -> *mut u8 {
917 self.0.as_ptr()
918 }
919
920 /// Gets a [`PtrMut`] from this with a smaller lifetime.
921 #[inline]
922 pub fn reborrow(&mut self) -> PtrMut<'_, A> {
923 // SAFETY: the ptrmut we're borrowing from is assumed to be valid
924 unsafe { PtrMut::new(self.0) }
925 }
926
927 /// Gets an immutable reference from this mutable reference
928 #[inline]
929 pub fn as_ref(&self) -> Ptr<'_, A> {
930 // SAFETY: The `PtrMut` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees
931 unsafe { Ptr::new(self.0) }
932 }
933}
934
935impl<'a, T: ?Sized> From<&'a mut T> for PtrMut<'a> {
936 #[inline]
937 fn from(val: &'a mut T) -> Self {
938 // SAFETY: The returned pointer has the same lifetime as the passed reference.
939 // The reference is mutable, and thus will not alias.
940 unsafe { Self::new(NonNull::from(val).cast()) }
941 }
942}
943
944impl<'a> OwningPtr<'a> {
945 /// This exists mostly to reduce compile times;
946 /// code is only duplicated per type, rather than per function called.
947 ///
948 /// # Safety
949 ///
950 /// Safety constraints of [`PtrMut::promote`] must be upheld.
951 unsafe fn make_internal<T>(temp: &mut ManuallyDrop<T>) -> OwningPtr<'_> {
952 // SAFETY: The constraints of `promote` are upheld by caller.
953 unsafe { PtrMut::from(&mut *temp).promote() }
954 }
955
956 /// Consumes a value and creates an [`OwningPtr`] to it while ensuring a double drop does not happen.
957 #[inline]
958 pub fn make<T, F: FnOnce(OwningPtr<'_>) -> R, R>(val: T, f: F) -> R {
959 let mut val = ManuallyDrop::new(val);
960 // SAFETY: The value behind the pointer will not get dropped or observed later,
961 // so it's safe to promote it to an owning pointer.
962 f(unsafe { Self::make_internal(&mut val) })
963 }
964}
965
966impl<'a, A: IsAligned> OwningPtr<'a, A> {
967 /// Creates a new instance from a raw pointer.
968 ///
969 /// # Safety
970 /// - `inner` must point to valid value of whatever the pointee type is.
971 /// - If the `A` type parameter is [`Aligned`] then `inner` must be [properly aligned] for the pointee type.
972 /// - `inner` must have correct provenance to allow read and writes of the pointee type.
973 /// - The lifetime `'a` must be constrained such that this [`OwningPtr`] will stay valid and nothing
974 /// else can read or mutate the pointee while this [`OwningPtr`] is live.
975 ///
976 /// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
977 #[inline]
978 pub unsafe fn new(inner: NonNull<u8>) -> Self {
979 Self(inner, PhantomData)
980 }
981
982 /// Consumes the [`OwningPtr`] to obtain ownership of the underlying data of type `T`.
983 ///
984 /// # Safety
985 /// - `T` must be the erased pointee type for this [`OwningPtr`].
986 /// - If the type parameter `A` is [`Unaligned`] then this pointer must be [properly aligned]
987 /// for the pointee type `T`.
988 ///
989 /// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
990 #[inline]
991 pub unsafe fn read<T>(self) -> T {
992 let ptr = self.as_ptr().cast::<T>().debug_ensure_aligned();
993 // SAFETY: The caller ensure the pointee is of type `T` and uphold safety for `read`.
994 unsafe { ptr.read() }
995 }
996
997 /// Casts to a concrete type as a [`MovingPtr`].
998 ///
999 /// # Safety
1000 /// - `T` must be the erased pointee type for this [`OwningPtr`].
1001 #[inline]
1002 pub unsafe fn cast<T>(self) -> MovingPtr<'a, T, A> {
1003 MovingPtr(self.0.cast::<T>(), PhantomData)
1004 }
1005
1006 /// Consumes the [`OwningPtr`] to drop the underlying data of type `T`.
1007 ///
1008 /// # Safety
1009 /// - `T` must be the erased pointee type for this [`OwningPtr`].
1010 /// - If the type parameter `A` is [`Unaligned`] then this pointer must be [properly aligned]
1011 /// for the pointee type `T`.
1012 ///
1013 /// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
1014 #[inline]
1015 pub unsafe fn drop_as<T>(self) {
1016 let ptr = self.as_ptr().cast::<T>().debug_ensure_aligned();
1017 // SAFETY: The caller ensure the pointee is of type `T` and uphold safety for `drop_in_place`.
1018 unsafe {
1019 ptr.drop_in_place();
1020 }
1021 }
1022
1023 /// Gets the underlying pointer, erasing the associated lifetime.
1024 ///
1025 /// If possible, it is strongly encouraged to use the other more type-safe functions
1026 /// over this function.
1027 #[inline]
1028 pub fn as_ptr(&self) -> *mut u8 {
1029 self.0.as_ptr()
1030 }
1031
1032 /// Gets an immutable pointer from this owned pointer.
1033 #[inline]
1034 pub fn as_ref(&self) -> Ptr<'_, A> {
1035 // SAFETY: The `Owning` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees
1036 unsafe { Ptr::new(self.0) }
1037 }
1038
1039 /// Gets a mutable pointer from this owned pointer.
1040 #[inline]
1041 pub fn as_mut(&mut self) -> PtrMut<'_, A> {
1042 // SAFETY: The `Owning` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees
1043 unsafe { PtrMut::new(self.0) }
1044 }
1045}
1046
1047impl<'a> OwningPtr<'a, Unaligned> {
1048 /// Consumes the [`OwningPtr`] to obtain ownership of the underlying data of type `T`.
1049 ///
1050 /// # Safety
1051 /// - `T` must be the erased pointee type for this [`OwningPtr`].
1052 pub unsafe fn read_unaligned<T>(self) -> T {
1053 let ptr = self.as_ptr().cast::<T>();
1054 // SAFETY: The caller ensure the pointee is of type `T` and uphold safety for `read_unaligned`.
1055 unsafe { ptr.read_unaligned() }
1056 }
1057}
1058
1059/// Conceptually equivalent to `&'a [T]` but with length information cut out for performance
1060/// reasons.
1061///
1062/// Because this type does not store the length of the slice, it is unable to do any sort of bounds
1063/// checking. As such, only [`Self::get_unchecked()`] is available for indexing into the slice,
1064/// where the user is responsible for checking the bounds.
1065///
1066/// When compiled in debug mode (`#[cfg(debug_assertion)]`), this type will store the length of the
1067/// slice and perform bounds checking in [`Self::get_unchecked()`].
1068///
1069/// # Example
1070///
1071/// ```
1072/// # use core::mem::size_of;
1073/// # use bevy_ptr::ThinSlicePtr;
1074/// #
1075/// let slice: &[u32] = &[2, 4, 8];
1076/// let thin_slice = ThinSlicePtr::from(slice);
1077///
1078/// assert_eq!(*unsafe { thin_slice.get_unchecked(0) }, 2);
1079/// assert_eq!(*unsafe { thin_slice.get_unchecked(1) }, 4);
1080/// assert_eq!(*unsafe { thin_slice.get_unchecked(2) }, 8);
1081/// ```
1082pub struct ThinSlicePtr<'a, T> {
1083 ptr: NonNull<T>,
1084 #[cfg(debug_assertions)]
1085 len: usize,
1086 _marker: PhantomData<&'a [T]>,
1087}
1088
1089impl<'a, T> ThinSlicePtr<'a, T> {
1090 /// Indexes the slice without performing bounds checks.
1091 ///
1092 /// # Safety
1093 ///
1094 /// `index` must be in-bounds.
1095 #[inline]
1096 pub unsafe fn get_unchecked(&self, index: usize) -> &'a T {
1097 // We cannot use `debug_assert!` here because `self.len` does not exist when not in debug
1098 // mode.
1099 #[cfg(debug_assertions)]
1100 assert!(index < self.len, "tried to index out-of-bounds of a slice");
1101
1102 // SAFETY: The caller guarantees `index` is in-bounds so that the resulting pointer is
1103 // valid to dereference.
1104 unsafe { &*self.ptr.add(index).as_ptr() }
1105 }
1106
1107 /// Returns a slice without performing bounds checks.
1108 ///
1109 /// # Safety
1110 ///
1111 /// - There must be no mutable aliases for the lifetime `'a` to the slice. to the slice.
1112 /// - `len` must be less than or equal to the length of the slice.
1113 pub unsafe fn as_slice_unchecked(&self, len: usize) -> &'a [T] {
1114 #[cfg(debug_assertions)]
1115 assert!(len <= self.len, "tried to create an out-of-bounds slice");
1116
1117 // SAFETY:
1118 // - The caller guarantees `len` is not greater than the length of the slice.
1119 // - The caller guarantees the aliasing rules.
1120 // - `self.ptr` is a valid pointer for the type `T`.
1121 // - `len` is valid hence `len * size_of::<T>()` is less than `isize::MAX`.
1122 unsafe { core::slice::from_raw_parts(self.ptr.as_ptr(), len) }
1123 }
1124
1125 /// Indexes the slice without performing bounds checks.
1126 ///
1127 /// # Safety
1128 ///
1129 /// `index` must be in-bounds.
1130 #[deprecated(since = "0.18.0", note = "use get_unchecked() instead")]
1131 pub unsafe fn get(self, index: usize) -> &'a T {
1132 // SAFETY: The caller guarantees that `index` is in-bounds.
1133 unsafe { self.get_unchecked(index) }
1134 }
1135}
1136
1137impl<'a, T> ThinSlicePtr<'a, UnsafeCell<T>> {
1138 /// Returns a mutable reference of the slice
1139 ///
1140 /// # Safety
1141 ///
1142 /// - There must not be any aliases for the lifetime `'a` to the slice.
1143 /// - `len` must be less than or equal to the length of the slice.
1144 pub unsafe fn as_mut_slice_unchecked(&self, len: usize) -> &'a mut [T] {
1145 #[cfg(debug_assertions)]
1146 assert!(len <= self.len, "tried to create an out-of-bounds slice");
1147
1148 // SAFETY:
1149 // - The caller ensures no aliases exist and `len` is in-bounds.
1150 // - `self.ptr` is a valid pointer for the type `T`.
1151 // - `len` is valid hence `len * size_of::<T>()` is less than `isize::MAX`.
1152 unsafe { core::slice::from_raw_parts_mut(UnsafeCell::raw_get(self.ptr.as_ptr()), len) }
1153 }
1154
1155 /// Returns a slice pointer to the underlying type `T`.
1156 pub fn cast(&self) -> ThinSlicePtr<'a, T> {
1157 ThinSlicePtr {
1158 // SAFETY: `self.ptr` is non null hence `UnsafeCell::raw_get` always returns a non null pointer
1159 ptr: unsafe { NonNull::new_unchecked(UnsafeCell::raw_get(self.ptr.as_ptr())) },
1160 #[cfg(debug_assertions)]
1161 len: self.len,
1162 _marker: PhantomData,
1163 }
1164 }
1165}
1166
1167impl<'a, T> Clone for ThinSlicePtr<'a, T> {
1168 fn clone(&self) -> Self {
1169 *self
1170 }
1171}
1172
1173impl<'a, T> Copy for ThinSlicePtr<'a, T> {}
1174
1175impl<'a, T> From<&'a [T]> for ThinSlicePtr<'a, T> {
1176 #[inline]
1177 fn from(slice: &'a [T]) -> Self {
1178 let ptr = slice.as_ptr().cast_mut().debug_ensure_aligned();
1179
1180 Self {
1181 // SAFETY: A reference can never be null.
1182 ptr: unsafe { NonNull::new_unchecked(ptr) },
1183 #[cfg(debug_assertions)]
1184 len: slice.len(),
1185 _marker: PhantomData,
1186 }
1187 }
1188}
1189
1190mod private {
1191 use core::cell::UnsafeCell;
1192
1193 pub trait SealedUnsafeCell {}
1194 impl<'a, T> SealedUnsafeCell for &'a UnsafeCell<T> {}
1195}
1196
1197/// Extension trait for helper methods on [`UnsafeCell`]
1198pub trait UnsafeCellDeref<'a, T>: private::SealedUnsafeCell {
1199 /// # Safety
1200 /// - The returned value must be unique and not alias any mutable or immutable references to the contents of the [`UnsafeCell`].
1201 /// - 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).
1202 unsafe fn deref_mut(self) -> &'a mut T;
1203
1204 /// # Safety
1205 /// - For the lifetime `'a` of the returned value you must not construct a mutable reference to the contents of the [`UnsafeCell`].
1206 /// - 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).
1207 unsafe fn deref(self) -> &'a T;
1208
1209 /// Returns a copy of the contained value.
1210 ///
1211 /// # Safety
1212 /// - The [`UnsafeCell`] must not currently have a mutable reference to its content.
1213 /// - 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).
1214 unsafe fn read(self) -> T
1215 where
1216 T: Copy;
1217}
1218
1219impl<'a, T> UnsafeCellDeref<'a, T> for &'a UnsafeCell<T> {
1220 #[inline]
1221 unsafe fn deref_mut(self) -> &'a mut T {
1222 // SAFETY: The caller upholds the alias rules.
1223 unsafe { &mut *self.get() }
1224 }
1225 #[inline]
1226 unsafe fn deref(self) -> &'a T {
1227 // SAFETY: The caller upholds the alias rules.
1228 unsafe { &*self.get() }
1229 }
1230
1231 #[inline]
1232 unsafe fn read(self) -> T
1233 where
1234 T: Copy,
1235 {
1236 // SAFETY: The caller upholds the alias rules.
1237 unsafe { self.get().read() }
1238 }
1239}
1240
1241trait DebugEnsureAligned {
1242 fn debug_ensure_aligned(self) -> Self;
1243}
1244
1245// Disable this for miri runs as it already checks if pointer to reference
1246// casts are properly aligned.
1247#[cfg(all(debug_assertions, not(miri)))]
1248impl<T: Sized> DebugEnsureAligned for *mut T {
1249 #[track_caller]
1250 fn debug_ensure_aligned(self) -> Self {
1251 assert!(
1252 self.is_aligned(),
1253 "pointer is not aligned. Address {:p} does not have alignment {} for type {}",
1254 self,
1255 align_of::<T>(),
1256 core::any::type_name::<T>()
1257 );
1258 self
1259 }
1260}
1261
1262#[cfg(any(not(debug_assertions), miri))]
1263impl<T: Sized> DebugEnsureAligned for *mut T {
1264 #[inline(always)]
1265 fn debug_ensure_aligned(self) -> Self {
1266 self
1267 }
1268}
1269
1270/// Safely converts a owned value into a [`MovingPtr`] while minimizing the number of stack copies.
1271///
1272/// This cannot be used as expression and must be used as a statement. Internally this macro works via variable shadowing.
1273#[macro_export]
1274macro_rules! move_as_ptr {
1275 ($value: ident) => {
1276 let mut $value = core::mem::MaybeUninit::new($value);
1277 // SAFETY:
1278 // - This macro shadows a MaybeUninit value that took ownership of the original value.
1279 // it is impossible to refer to the original value, preventing further access after
1280 // the `MovingPtr` has been used. `MaybeUninit` also prevents the compiler from
1281 // dropping the original value.
1282 let $value = unsafe { $crate::MovingPtr::from_value(&mut $value) };
1283 };
1284}
1285
1286/// Helper macro used by [`deconstruct_moving_ptr`] to extract
1287/// the pattern from `field: pattern` or `field` shorthand.
1288#[macro_export]
1289#[doc(hidden)]
1290macro_rules! get_pattern {
1291 ($field_index:tt) => {
1292 $field_index
1293 };
1294 ($field_index:tt: $pattern:pat) => {
1295 $pattern
1296 };
1297}
1298
1299/// Deconstructs a [`MovingPtr`] into its individual fields.
1300///
1301/// This consumes the [`MovingPtr`] and hands out [`MovingPtr`] wrappers around
1302/// pointers to each of its fields. The value will *not* be dropped.
1303///
1304/// The macro should wrap a `let` expression with a struct pattern.
1305/// It does not support matching tuples by position,
1306/// so for tuple structs you should use `0: pat` syntax.
1307///
1308/// For tuples themselves, pass the identifier `tuple` instead of the struct name,
1309/// like `let tuple { 0: pat0, 1: pat1 } = value`.
1310///
1311/// This can also project into `MaybeUninit`.
1312/// Wrap the type name or `tuple` with `MaybeUninit::<_>`,
1313/// and the macro will deconstruct a `MovingPtr<MaybeUninit<ParentType>>`
1314/// into `MovingPtr<MaybeUninit<FieldType>>` values.
1315///
1316/// # Examples
1317///
1318/// ## Structs
1319///
1320/// ```
1321/// use core::mem::{offset_of, MaybeUninit};
1322/// use bevy_ptr::{MovingPtr, move_as_ptr};
1323/// # use bevy_ptr::Unaligned;
1324/// # struct FieldAType(usize);
1325/// # struct FieldBType(usize);
1326/// # struct FieldCType(usize);
1327///
1328/// # pub struct Parent {
1329/// # pub field_a: FieldAType,
1330/// # pub field_b: FieldBType,
1331/// # pub field_c: FieldCType,
1332/// # }
1333///
1334/// let parent = Parent {
1335/// field_a: FieldAType(11),
1336/// field_b: FieldBType(22),
1337/// field_c: FieldCType(33),
1338/// };
1339///
1340/// let mut target_a = FieldAType(101);
1341/// let mut target_b = FieldBType(102);
1342/// let mut target_c = FieldCType(103);
1343///
1344/// // Converts `parent` into a `MovingPtr`
1345/// move_as_ptr!(parent);
1346///
1347/// // The field names must match the name used in the type definition.
1348/// // Each one will be a `MovingPtr` of the field's type.
1349/// bevy_ptr::deconstruct_moving_ptr!({
1350/// let Parent { field_a, field_b, field_c } = parent;
1351/// });
1352///
1353/// field_a.assign_to(&mut target_a);
1354/// field_b.assign_to(&mut target_b);
1355/// field_c.assign_to(&mut target_c);
1356///
1357/// assert_eq!(target_a.0, 11);
1358/// assert_eq!(target_b.0, 22);
1359/// assert_eq!(target_c.0, 33);
1360/// ```
1361///
1362/// ## Tuples
1363///
1364/// ```
1365/// use core::mem::{offset_of, MaybeUninit};
1366/// use bevy_ptr::{MovingPtr, move_as_ptr};
1367/// # use bevy_ptr::Unaligned;
1368/// # struct FieldAType(usize);
1369/// # struct FieldBType(usize);
1370/// # struct FieldCType(usize);
1371///
1372/// # pub struct Parent {
1373/// # pub field_a: FieldAType,
1374/// # pub field_b: FieldBType,
1375/// # pub field_c: FieldCType,
1376/// # }
1377///
1378/// let parent = (
1379/// FieldAType(11),
1380/// FieldBType(22),
1381/// FieldCType(33),
1382/// );
1383///
1384/// let mut target_a = FieldAType(101);
1385/// let mut target_b = FieldBType(102);
1386/// let mut target_c = FieldCType(103);
1387///
1388/// // Converts `parent` into a `MovingPtr`
1389/// move_as_ptr!(parent);
1390///
1391/// // The field names must match the name used in the type definition.
1392/// // Each one will be a `MovingPtr` of the field's type.
1393/// bevy_ptr::deconstruct_moving_ptr!({
1394/// let tuple { 0: field_a, 1: field_b, 2: field_c } = parent;
1395/// });
1396///
1397/// field_a.assign_to(&mut target_a);
1398/// field_b.assign_to(&mut target_b);
1399/// field_c.assign_to(&mut target_c);
1400///
1401/// assert_eq!(target_a.0, 11);
1402/// assert_eq!(target_b.0, 22);
1403/// assert_eq!(target_c.0, 33);
1404/// ```
1405///
1406/// ## `MaybeUninit`
1407///
1408/// ```
1409/// use core::mem::{offset_of, MaybeUninit};
1410/// use bevy_ptr::{MovingPtr, move_as_ptr};
1411/// # use bevy_ptr::Unaligned;
1412/// # struct FieldAType(usize);
1413/// # struct FieldBType(usize);
1414/// # struct FieldCType(usize);
1415///
1416/// # pub struct Parent {
1417/// # pub field_a: FieldAType,
1418/// # pub field_b: FieldBType,
1419/// # pub field_c: FieldCType,
1420/// # }
1421///
1422/// let parent = MaybeUninit::new(Parent {
1423/// field_a: FieldAType(11),
1424/// field_b: FieldBType(22),
1425/// field_c: FieldCType(33),
1426/// });
1427///
1428/// let mut target_a = MaybeUninit::new(FieldAType(101));
1429/// let mut target_b = MaybeUninit::new(FieldBType(102));
1430/// let mut target_c = MaybeUninit::new(FieldCType(103));
1431///
1432/// // Converts `parent` into a `MovingPtr`
1433/// move_as_ptr!(parent);
1434///
1435/// // The field names must match the name used in the type definition.
1436/// // Each one will be a `MovingPtr` of the field's type.
1437/// bevy_ptr::deconstruct_moving_ptr!({
1438/// let MaybeUninit::<Parent> { field_a, field_b, field_c } = parent;
1439/// });
1440///
1441/// field_a.assign_to(&mut target_a);
1442/// field_b.assign_to(&mut target_b);
1443/// field_c.assign_to(&mut target_c);
1444///
1445/// unsafe {
1446/// assert_eq!(target_a.assume_init().0, 11);
1447/// assert_eq!(target_b.assume_init().0, 22);
1448/// assert_eq!(target_c.assume_init().0, 33);
1449/// }
1450/// ```
1451///
1452/// [`assign_to`]: MovingPtr::assign_to
1453#[macro_export]
1454macro_rules! deconstruct_moving_ptr {
1455 ({ let tuple { $($field_index:tt: $pattern:pat),* $(,)? } = $ptr:expr ;}) => {
1456 // Specify the type to make sure the `mem::forget` doesn't forget a mere `&mut MovingPtr`
1457 let mut ptr: $crate::MovingPtr<_, _> = $ptr;
1458 let _ = || {
1459 let value = &mut *ptr;
1460 // Ensure that each field index exists and is mentioned only once
1461 // Ensure that the struct is not `repr(packed)` and that we may take references to fields
1462 core::hint::black_box(($(&mut value.$field_index,)*));
1463 // Ensure that `ptr` is a tuple and not something that derefs to it
1464 // Ensure that the number of patterns matches the number of fields
1465 fn unreachable<T>(_index: usize) -> T {
1466 unreachable!()
1467 }
1468 *value = ($(unreachable($field_index),)*);
1469 };
1470 // SAFETY:
1471 // - `f` does a raw pointer offset, which always returns a non-null pointer to a field inside `T`
1472 // - The struct is not `repr(packed)`, since otherwise the block of code above would fail compilation
1473 // - `mem::forget` is called on `self` immediately after these calls
1474 // - Each field is distinct, since otherwise the block of code above would fail compilation
1475 $(let $pattern = unsafe { ptr.move_field(|f| &raw mut (*f).$field_index) };)*
1476 core::mem::forget(ptr);
1477 };
1478 ({ let MaybeUninit::<tuple> { $($field_index:tt: $pattern:pat),* $(,)? } = $ptr:expr ;}) => {
1479 // Specify the type to make sure the `mem::forget` doesn't forget a mere `&mut MovingPtr`
1480 let mut ptr: $crate::MovingPtr<core::mem::MaybeUninit<_>, _> = $ptr;
1481 let _ = || {
1482 // SAFETY: This closure is never called
1483 let value = unsafe { ptr.assume_init_mut() };
1484 // Ensure that each field index exists and is mentioned only once
1485 // Ensure that the struct is not `repr(packed)` and that we may take references to fields
1486 core::hint::black_box(($(&mut value.$field_index,)*));
1487 // Ensure that `ptr` is a tuple and not something that derefs to it
1488 // Ensure that the number of patterns matches the number of fields
1489 fn unreachable<T>(_index: usize) -> T {
1490 unreachable!()
1491 }
1492 *value = ($(unreachable($field_index),)*);
1493 };
1494 // SAFETY:
1495 // - `f` does a raw pointer offset, which always returns a non-null pointer to a field inside `T`
1496 // - The struct is not `repr(packed)`, since otherwise the block of code above would fail compilation
1497 // - `mem::forget` is called on `self` immediately after these calls
1498 // - Each field is distinct, since otherwise the block of code above would fail compilation
1499 $(let $pattern = unsafe { ptr.move_maybe_uninit_field(|f| &raw mut (*f).$field_index) };)*
1500 core::mem::forget(ptr);
1501 };
1502 ({ let $struct_name:ident { $($field_index:tt$(: $pattern:pat)?),* $(,)? } = $ptr:expr ;}) => {
1503 // Specify the type to make sure the `mem::forget` doesn't forget a mere `&mut MovingPtr`
1504 let mut ptr: $crate::MovingPtr<_, _> = $ptr;
1505 let _ = || {
1506 let value = &mut *ptr;
1507 // Ensure that each field index exists is mentioned only once
1508 // Ensure that each field is on the struct and not accessed using autoref
1509 let $struct_name { $($field_index: _),* } = value;
1510 // Ensure that the struct is not `repr(packed)` and that we may take references to fields
1511 core::hint::black_box(($(&mut value.$field_index),*));
1512 // Ensure that `ptr` is a `$struct_name` and not just something that derefs to it
1513 let value: *mut _ = value;
1514 // SAFETY: This closure is never called
1515 $struct_name { ..unsafe { value.read() } };
1516 };
1517 // SAFETY:
1518 // - `f` does a raw pointer offset, which always returns a non-null pointer to a field inside `T`
1519 // - The struct is not `repr(packed)`, since otherwise the block of code above would fail compilation
1520 // - `mem::forget` is called on `self` immediately after these calls
1521 // - Each field is distinct, since otherwise the block of code above would fail compilation
1522 $(let $crate::get_pattern!($field_index$(: $pattern)?) = unsafe { ptr.move_field(|f| &raw mut (*f).$field_index) };)*
1523 core::mem::forget(ptr);
1524 };
1525 ({ let MaybeUninit::<$struct_name:ident> { $($field_index:tt$(: $pattern:pat)?),* $(,)? } = $ptr:expr ;}) => {
1526 // Specify the type to make sure the `mem::forget` doesn't forget a mere `&mut MovingPtr`
1527 let mut ptr: $crate::MovingPtr<core::mem::MaybeUninit<_>, _> = $ptr;
1528 let _ = || {
1529 // SAFETY: This closure is never called
1530 let value = unsafe { ptr.assume_init_mut() };
1531 // Ensure that each field index exists is mentioned only once
1532 // Ensure that each field is on the struct and not accessed using autoref
1533 let $struct_name { $($field_index: _),* } = value;
1534 // Ensure that the struct is not `repr(packed)` and that we may take references to fields
1535 core::hint::black_box(($(&mut value.$field_index),*));
1536 // Ensure that `ptr` is a `$struct_name` and not just something that derefs to it
1537 let value: *mut _ = value;
1538 // SAFETY: This closure is never called
1539 $struct_name { ..unsafe { value.read() } };
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 $crate::get_pattern!($field_index$(: $pattern)?) = unsafe { ptr.move_maybe_uninit_field(|f| &raw mut (*f).$field_index) };)*
1547 core::mem::forget(ptr);
1548 };
1549}