Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ptr/src/lib.rs
6849 views
1
#![doc = include_str!("../README.md")]
2
#![no_std]
3
#![cfg_attr(docsrs, feature(doc_auto_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
10
use core::{
11
cell::UnsafeCell,
12
fmt::{self, Debug, Formatter, Pointer},
13
marker::PhantomData,
14
mem::{self, ManuallyDrop, MaybeUninit},
15
num::NonZeroUsize,
16
ops::{Deref, DerefMut},
17
ptr::{self, NonNull},
18
};
19
20
/// Used as a type argument to [`Ptr`], [`PtrMut`], [`OwningPtr`], and [`MovingPtr`] to specify that the pointer is guaranteed
21
/// to be [aligned].
22
///
23
/// [aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
24
#[derive(Debug, Copy, Clone)]
25
pub struct Aligned;
26
27
/// Used as a type argument to [`Ptr`], [`PtrMut`], [`OwningPtr`], and [`MovingPtr`] to specify that the pointer may not [aligned].
28
///
29
/// [aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
30
#[derive(Debug, Copy, Clone)]
31
pub struct Unaligned;
32
33
/// Trait that is only implemented for [`Aligned`] and [`Unaligned`] to work around the lack of ability
34
/// to have const generics of an enum.
35
pub trait IsAligned: sealed::Sealed {
36
/// Reads the value pointed to by `ptr`.
37
///
38
/// # Safety
39
/// - `ptr` must be valid for reads.
40
/// - `ptr` must point to a valid instance of type `T`
41
/// - If this type is [`Aligned`], then `ptr` must be [properly aligned] for type `T`.
42
///
43
/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
44
#[doc(hidden)]
45
unsafe fn read_ptr<T>(ptr: *const T) -> T;
46
47
/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
48
/// and destination must *not* overlap.
49
///
50
/// # Safety
51
/// - `src` must be valid for reads of `count * size_of::<T>()` bytes.
52
/// - `dst` must be valid for writes of `count * size_of::<T>()` bytes.
53
/// - The region of memory beginning at `src` with a size of `count *
54
/// size_of::<T>()` bytes must *not* overlap with the region of memory
55
/// beginning at `dst` with the same size.
56
/// - If this type is [`Aligned`], then both `src` and `dst` must properly
57
/// be aligned for values of type `T`.
58
#[doc(hidden)]
59
unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
60
61
/// Reads the value pointed to by `ptr`.
62
///
63
/// # Safety
64
/// - `ptr` must be valid for reads and writes.
65
/// - `ptr` must point to a valid instance of type `T`
66
/// - If this type is [`Aligned`], then `ptr` must be [properly aligned] for type `T`.
67
/// - The value pointed to by `ptr` must be valid for dropping.
68
/// - While `drop_in_place` is executing, the only way to access parts of `ptr` is through
69
/// the `&mut Self` supplied to it's `Drop::drop` impl.
70
///
71
/// [properly aligned]: https://doc.rust-lang.org/std/ptr/index.html#alignment
72
#[doc(hidden)]
73
unsafe fn drop_in_place<T>(ptr: *mut T);
74
}
75
76
impl IsAligned for Aligned {
77
#[inline]
78
unsafe fn read_ptr<T>(ptr: *const T) -> T {
79
// SAFETY:
80
// - The caller is required to ensure that `src` must be valid for reads.
81
// - The caller is required to ensure that `src` points to a valid instance of type `T`.
82
// - This type is `Aligned` so the caller must ensure that `src` is properly aligned for type `T`.
83
unsafe { ptr.read() }
84
}
85
86
#[inline]
87
unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
88
// SAFETY:
89
// - The caller is required to ensure that `src` must be valid for reads.
90
// - The caller is required to ensure that `dst` must be valid for writes.
91
// - The caller is required to ensure that `src` and `dst` are aligned.
92
// - The caller is required to ensure that the memory region covered by `src`
93
// and `dst`, fitting up to `count` elements do not overlap.
94
unsafe {
95
ptr::copy_nonoverlapping(src, dst, count);
96
}
97
}
98
99
#[inline]
100
unsafe fn drop_in_place<T>(ptr: *mut T) {
101
// SAFETY:
102
// - The caller is required to ensure that `ptr` must be valid for reads and writes.
103
// - The caller is required to ensure that `ptr` points to a valid instance of type `T`.
104
// - This type is `Aligned` so the caller must ensure that `ptr` is properly aligned for type `T`.
105
// - The caller is required to ensure that `ptr` points must be valid for dropping.
106
// - The caller is required to ensure that the value `ptr` points must not be used after this function
107
// call.
108
unsafe {
109
ptr::drop_in_place(ptr);
110
}
111
}
112
}
113
114
impl IsAligned for Unaligned {
115
#[inline]
116
unsafe fn read_ptr<T>(ptr: *const T) -> T {
117
// SAFETY:
118
// - The caller is required to ensure that `src` must be valid for reads.
119
// - The caller is required to ensure that `src` points to a valid instance of type `T`.
120
unsafe { ptr.read_unaligned() }
121
}
122
123
#[inline]
124
unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
125
// SAFETY:
126
// - The caller is required to ensure that `src` must be valid for reads.
127
// - The caller is required to ensure that `dst` must be valid for writes.
128
// - This is doing a byte-wise copy. `src` and `dst` are always guaranteed to be
129
// aligned.
130
// - The caller is required to ensure that the memory region covered by `src`
131
// and `dst`, fitting up to `count` elements do not overlap.
132
unsafe {
133
ptr::copy_nonoverlapping::<u8>(
134
src.cast::<u8>(),
135
dst.cast::<u8>(),
136
count * size_of::<T>(),
137
);
138
}
139
}
140
141
#[inline]
142
unsafe fn drop_in_place<T>(ptr: *mut T) {
143
// SAFETY:
144
// - The caller is required to ensure that `ptr` must be valid for reads and writes.
145
// - The caller is required to ensure that `ptr` points to a valid instance of type `T`.
146
// - This type is not `Aligned` so the caller does not need to ensure that `ptr` is properly aligned for type `T`.
147
// - The caller is required to ensure that `ptr` points must be valid for dropping.
148
// - The caller is required to ensure that the value `ptr` points must not be used after this function
149
// call.
150
unsafe {
151
drop(ptr.read_unaligned());
152
}
153
}
154
}
155
156
mod sealed {
157
pub trait Sealed {}
158
impl Sealed for super::Aligned {}
159
impl Sealed for super::Unaligned {}
160
}
161
162
/// A newtype around [`NonNull`] that only allows conversion to read-only borrows or pointers.
163
///
164
/// This type can be thought of as the `*const T` to [`NonNull<T>`]'s `*mut T`.
165
#[repr(transparent)]
166
pub struct ConstNonNull<T: ?Sized>(NonNull<T>);
167
168
impl<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
259
impl<T: ?Sized> From<NonNull<T>> for ConstNonNull<T> {
260
fn from(value: NonNull<T>) -> ConstNonNull<T> {
261
ConstNonNull(value)
262
}
263
}
264
265
impl<'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
271
impl<'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)]
291
pub 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)]
307
pub 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)]
329
pub 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)]
353
pub struct MovingPtr<'a, T, A: IsAligned = Aligned>(NonNull<T>, PhantomData<(&'a mut T, A)>);
354
355
macro_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
439
impl_ptr!(Ptr);
440
impl_ptr!(PtrMut);
441
impl_ptr!(OwningPtr);
442
443
impl<'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
469
impl<'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 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 exctra 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
680
impl<'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
712
impl<'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
729
impl<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
736
impl<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
743
impl<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
750
impl<'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
765
impl<'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
779
impl<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
789
impl<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
798
impl<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
810
impl<'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 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 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
862
impl<'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
871
impl<'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 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 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
935
impl<'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
944
impl<'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
966
impl<'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 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 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
1047
impl<'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 reasons
1060
pub struct ThinSlicePtr<'a, T> {
1061
ptr: NonNull<T>,
1062
#[cfg(debug_assertions)]
1063
len: usize,
1064
_marker: PhantomData<&'a [T]>,
1065
}
1066
1067
impl<'a, T> ThinSlicePtr<'a, T> {
1068
#[inline]
1069
/// Indexes the slice without doing bounds checks
1070
///
1071
/// # Safety
1072
/// `index` must be in-bounds.
1073
pub unsafe fn get(self, index: usize) -> &'a T {
1074
#[cfg(debug_assertions)]
1075
debug_assert!(index < self.len);
1076
1077
let ptr = self.ptr.as_ptr();
1078
// SAFETY: `index` is in-bounds so the resulting pointer is valid to dereference.
1079
unsafe { &*ptr.add(index) }
1080
}
1081
}
1082
1083
impl<'a, T> Clone for ThinSlicePtr<'a, T> {
1084
fn clone(&self) -> Self {
1085
*self
1086
}
1087
}
1088
1089
impl<'a, T> Copy for ThinSlicePtr<'a, T> {}
1090
1091
impl<'a, T> From<&'a [T]> for ThinSlicePtr<'a, T> {
1092
#[inline]
1093
fn from(slice: &'a [T]) -> Self {
1094
let ptr = slice.as_ptr().cast_mut();
1095
Self {
1096
// SAFETY: a reference can never be null
1097
ptr: unsafe { NonNull::new_unchecked(ptr.debug_ensure_aligned()) },
1098
#[cfg(debug_assertions)]
1099
len: slice.len(),
1100
_marker: PhantomData,
1101
}
1102
}
1103
}
1104
1105
/// Creates a dangling pointer with specified alignment.
1106
/// See [`NonNull::dangling`].
1107
pub const fn dangling_with_align(align: NonZeroUsize) -> NonNull<u8> {
1108
debug_assert!(align.is_power_of_two(), "Alignment must be power of two.");
1109
// SAFETY: The pointer will not be null, since it was created
1110
// from the address of a `NonZero<usize>`.
1111
// TODO: use https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.with_addr once stabilized
1112
unsafe { NonNull::new_unchecked(ptr::null_mut::<u8>().wrapping_add(align.get())) }
1113
}
1114
1115
mod private {
1116
use core::cell::UnsafeCell;
1117
1118
pub trait SealedUnsafeCell {}
1119
impl<'a, T> SealedUnsafeCell for &'a UnsafeCell<T> {}
1120
}
1121
1122
/// Extension trait for helper methods on [`UnsafeCell`]
1123
pub trait UnsafeCellDeref<'a, T>: private::SealedUnsafeCell {
1124
/// # Safety
1125
/// - The returned value must be unique and not alias any mutable or immutable references to the contents of the [`UnsafeCell`].
1126
/// - 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).
1127
unsafe fn deref_mut(self) -> &'a mut T;
1128
1129
/// # Safety
1130
/// - For the lifetime `'a` of the returned value you must not construct a mutable reference to the contents of the [`UnsafeCell`].
1131
/// - 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).
1132
unsafe fn deref(self) -> &'a T;
1133
1134
/// Returns a copy of the contained value.
1135
///
1136
/// # Safety
1137
/// - The [`UnsafeCell`] must not currently have a mutable reference to its content.
1138
/// - 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).
1139
unsafe fn read(self) -> T
1140
where
1141
T: Copy;
1142
}
1143
1144
impl<'a, T> UnsafeCellDeref<'a, T> for &'a UnsafeCell<T> {
1145
#[inline]
1146
unsafe fn deref_mut(self) -> &'a mut T {
1147
// SAFETY: The caller upholds the alias rules.
1148
unsafe { &mut *self.get() }
1149
}
1150
#[inline]
1151
unsafe fn deref(self) -> &'a T {
1152
// SAFETY: The caller upholds the alias rules.
1153
unsafe { &*self.get() }
1154
}
1155
1156
#[inline]
1157
unsafe fn read(self) -> T
1158
where
1159
T: Copy,
1160
{
1161
// SAFETY: The caller upholds the alias rules.
1162
unsafe { self.get().read() }
1163
}
1164
}
1165
1166
trait DebugEnsureAligned {
1167
fn debug_ensure_aligned(self) -> Self;
1168
}
1169
1170
// Disable this for miri runs as it already checks if pointer to reference
1171
// casts are properly aligned.
1172
#[cfg(all(debug_assertions, not(miri)))]
1173
impl<T: Sized> DebugEnsureAligned for *mut T {
1174
#[track_caller]
1175
fn debug_ensure_aligned(self) -> Self {
1176
let align = align_of::<T>();
1177
// Implementation shamelessly borrowed from the currently unstable
1178
// ptr.is_aligned_to.
1179
//
1180
// Replace once https://github.com/rust-lang/rust/issues/96284 is stable.
1181
assert_eq!(
1182
self as usize & (align - 1),
1183
0,
1184
"pointer is not aligned. Address {:p} does not have alignment {} for type {}",
1185
self,
1186
align,
1187
core::any::type_name::<T>()
1188
);
1189
self
1190
}
1191
}
1192
1193
#[cfg(any(not(debug_assertions), miri))]
1194
impl<T: Sized> DebugEnsureAligned for *mut T {
1195
#[inline(always)]
1196
fn debug_ensure_aligned(self) -> Self {
1197
self
1198
}
1199
}
1200
1201
/// Safely converts a owned value into a [`MovingPtr`] while minimizing the number of stack copies.
1202
///
1203
/// This cannot be used as expression and must be used as a statement. Internally this macro works via variable shadowing.
1204
#[macro_export]
1205
macro_rules! move_as_ptr {
1206
($value: ident) => {
1207
let mut $value = core::mem::MaybeUninit::new($value);
1208
// SAFETY:
1209
// - This macro shadows a MaybeUninit value that took ownership of the original value.
1210
// it is impossible to refer to the original value, preventing further access after
1211
// the `MovingPtr` has been used. `MaybeUninit` also prevents the compiler from
1212
// dropping the original value.
1213
let $value = unsafe { $crate::MovingPtr::from_value(&mut $value) };
1214
};
1215
}
1216
1217
/// Helper macro used by [`deconstruct_moving_ptr`] to to extract
1218
/// the pattern from `field: pattern` or `field` shorthand.
1219
#[macro_export]
1220
#[doc(hidden)]
1221
macro_rules! get_pattern {
1222
($field_index:tt) => {
1223
$field_index
1224
};
1225
($field_index:tt: $pattern:pat) => {
1226
$pattern
1227
};
1228
}
1229
1230
/// Deconstructs a [`MovingPtr`] into its individual fields.
1231
///
1232
/// This consumes the [`MovingPtr`] and hands out [`MovingPtr`] wrappers around
1233
/// pointers to each of its fields. The value will *not* be dropped.
1234
///
1235
/// The macro should wrap a `let` expression with a struct pattern.
1236
/// It does not support matching tuples by position,
1237
/// so for tuple structs you should use `0: pat` syntax.
1238
///
1239
/// For tuples themselves, pass the identifier `tuple` instead of the struct name,
1240
/// like `let tuple { 0: pat0, 1: pat1 } = value`.
1241
///
1242
/// This can also project into `MaybeUninit`.
1243
/// Wrap the type name or `tuple` with `MaybeUninit::<_>`,
1244
/// and the macro will deconstruct a `MovingPtr<MaybeUninit<ParentType>>`
1245
/// into `MovingPtr<MaybeUninit<FieldType>>` values.
1246
///
1247
/// # Examples
1248
///
1249
/// ## Structs
1250
///
1251
/// ```
1252
/// use core::mem::{offset_of, MaybeUninit};
1253
/// use bevy_ptr::{MovingPtr, move_as_ptr};
1254
/// # use bevy_ptr::Unaligned;
1255
/// # struct FieldAType(usize);
1256
/// # struct FieldBType(usize);
1257
/// # struct FieldCType(usize);
1258
///
1259
/// # pub struct Parent {
1260
/// # pub field_a: FieldAType,
1261
/// # pub field_b: FieldBType,
1262
/// # pub field_c: FieldCType,
1263
/// # }
1264
///
1265
/// let parent = Parent {
1266
/// field_a: FieldAType(11),
1267
/// field_b: FieldBType(22),
1268
/// field_c: FieldCType(33),
1269
/// };
1270
///
1271
/// let mut target_a = FieldAType(101);
1272
/// let mut target_b = FieldBType(102);
1273
/// let mut target_c = FieldCType(103);
1274
///
1275
/// // Converts `parent` into a `MovingPtr`
1276
/// move_as_ptr!(parent);
1277
///
1278
/// // The field names must match the name used in the type definition.
1279
/// // Each one will be a `MovingPtr` of the field's type.
1280
/// bevy_ptr::deconstruct_moving_ptr!({
1281
/// let Parent { field_a, field_b, field_c } = parent;
1282
/// });
1283
///
1284
/// field_a.assign_to(&mut target_a);
1285
/// field_b.assign_to(&mut target_b);
1286
/// field_c.assign_to(&mut target_c);
1287
///
1288
/// assert_eq!(target_a.0, 11);
1289
/// assert_eq!(target_b.0, 22);
1290
/// assert_eq!(target_c.0, 33);
1291
/// ```
1292
///
1293
/// ## Tuples
1294
///
1295
/// ```
1296
/// use core::mem::{offset_of, MaybeUninit};
1297
/// use bevy_ptr::{MovingPtr, move_as_ptr};
1298
/// # use bevy_ptr::Unaligned;
1299
/// # struct FieldAType(usize);
1300
/// # struct FieldBType(usize);
1301
/// # struct FieldCType(usize);
1302
///
1303
/// # pub struct Parent {
1304
/// # pub field_a: FieldAType,
1305
/// # pub field_b: FieldBType,
1306
/// # pub field_c: FieldCType,
1307
/// # }
1308
///
1309
/// let parent = (
1310
/// FieldAType(11),
1311
/// FieldBType(22),
1312
/// FieldCType(33),
1313
/// );
1314
///
1315
/// let mut target_a = FieldAType(101);
1316
/// let mut target_b = FieldBType(102);
1317
/// let mut target_c = FieldCType(103);
1318
///
1319
/// // Converts `parent` into a `MovingPtr`
1320
/// move_as_ptr!(parent);
1321
///
1322
/// // The field names must match the name used in the type definition.
1323
/// // Each one will be a `MovingPtr` of the field's type.
1324
/// bevy_ptr::deconstruct_moving_ptr!({
1325
/// let tuple { 0: field_a, 1: field_b, 2: field_c } = parent;
1326
/// });
1327
///
1328
/// field_a.assign_to(&mut target_a);
1329
/// field_b.assign_to(&mut target_b);
1330
/// field_c.assign_to(&mut target_c);
1331
///
1332
/// assert_eq!(target_a.0, 11);
1333
/// assert_eq!(target_b.0, 22);
1334
/// assert_eq!(target_c.0, 33);
1335
/// ```
1336
///
1337
/// ## `MaybeUninit`
1338
///
1339
/// ```
1340
/// use core::mem::{offset_of, MaybeUninit};
1341
/// use bevy_ptr::{MovingPtr, move_as_ptr};
1342
/// # use bevy_ptr::Unaligned;
1343
/// # struct FieldAType(usize);
1344
/// # struct FieldBType(usize);
1345
/// # struct FieldCType(usize);
1346
///
1347
/// # pub struct Parent {
1348
/// # pub field_a: FieldAType,
1349
/// # pub field_b: FieldBType,
1350
/// # pub field_c: FieldCType,
1351
/// # }
1352
///
1353
/// let parent = MaybeUninit::new(Parent {
1354
/// field_a: FieldAType(11),
1355
/// field_b: FieldBType(22),
1356
/// field_c: FieldCType(33),
1357
/// });
1358
///
1359
/// let mut target_a = MaybeUninit::new(FieldAType(101));
1360
/// let mut target_b = MaybeUninit::new(FieldBType(102));
1361
/// let mut target_c = MaybeUninit::new(FieldCType(103));
1362
///
1363
/// // Converts `parent` into a `MovingPtr`
1364
/// move_as_ptr!(parent);
1365
///
1366
/// // The field names must match the name used in the type definition.
1367
/// // Each one will be a `MovingPtr` of the field's type.
1368
/// bevy_ptr::deconstruct_moving_ptr!({
1369
/// let MaybeUninit::<Parent> { field_a, field_b, field_c } = parent;
1370
/// });
1371
///
1372
/// field_a.assign_to(&mut target_a);
1373
/// field_b.assign_to(&mut target_b);
1374
/// field_c.assign_to(&mut target_c);
1375
///
1376
/// unsafe {
1377
/// assert_eq!(target_a.assume_init().0, 11);
1378
/// assert_eq!(target_b.assume_init().0, 22);
1379
/// assert_eq!(target_c.assume_init().0, 33);
1380
/// }
1381
/// ```
1382
///
1383
/// [`assign_to`]: MovingPtr::assign_to
1384
#[macro_export]
1385
macro_rules! deconstruct_moving_ptr {
1386
({ let tuple { $($field_index:tt: $pattern:pat),* $(,)? } = $ptr:expr ;}) => {
1387
// Specify the type to make sure the `mem::forget` doesn't forget a mere `&mut MovingPtr`
1388
let mut ptr: $crate::MovingPtr<_, _> = $ptr;
1389
let _ = || {
1390
let value = &mut *ptr;
1391
// Ensure that each field index exists and is mentioned only once
1392
// Ensure that the struct is not `repr(packed)` and that we may take references to fields
1393
core::hint::black_box(($(&mut value.$field_index,)*));
1394
// Ensure that `ptr` is a tuple and not something that derefs to it
1395
// Ensure that the number of patterns matches the number of fields
1396
fn unreachable<T>(_index: usize) -> T {
1397
unreachable!()
1398
}
1399
*value = ($(unreachable($field_index),)*);
1400
};
1401
// SAFETY:
1402
// - `f` does a raw pointer offset, which always returns a non-null pointer to a field inside `T`
1403
// - The struct is not `repr(packed)`, since otherwise the block of code above would fail compilation
1404
// - `mem::forget` is called on `self` immediately after these calls
1405
// - Each field is distinct, since otherwise the block of code above would fail compilation
1406
$(let $pattern = unsafe { ptr.move_field(|f| &raw mut (*f).$field_index) };)*
1407
core::mem::forget(ptr);
1408
};
1409
({ let MaybeUninit::<tuple> { $($field_index:tt: $pattern:pat),* $(,)? } = $ptr:expr ;}) => {
1410
// Specify the type to make sure the `mem::forget` doesn't forget a mere `&mut MovingPtr`
1411
let mut ptr: $crate::MovingPtr<core::mem::MaybeUninit<_>, _> = $ptr;
1412
let _ = || {
1413
// SAFETY: This closure is never called
1414
let value = unsafe { ptr.assume_init_mut() };
1415
// Ensure that each field index exists and is mentioned only once
1416
// Ensure that the struct is not `repr(packed)` and that we may take references to fields
1417
core::hint::black_box(($(&mut value.$field_index,)*));
1418
// Ensure that `ptr` is a tuple and not something that derefs to it
1419
// Ensure that the number of patterns matches the number of fields
1420
fn unreachable<T>(_index: usize) -> T {
1421
unreachable!()
1422
}
1423
*value = ($(unreachable($field_index),)*);
1424
};
1425
// SAFETY:
1426
// - `f` does a raw pointer offset, which always returns a non-null pointer to a field inside `T`
1427
// - The struct is not `repr(packed)`, since otherwise the block of code above would fail compilation
1428
// - `mem::forget` is called on `self` immediately after these calls
1429
// - Each field is distinct, since otherwise the block of code above would fail compilation
1430
$(let $pattern = unsafe { ptr.move_maybe_uninit_field(|f| &raw mut (*f).$field_index) };)*
1431
core::mem::forget(ptr);
1432
};
1433
({ let $struct_name:ident { $($field_index:tt$(: $pattern:pat)?),* $(,)? } = $ptr:expr ;}) => {
1434
// Specify the type to make sure the `mem::forget` doesn't forget a mere `&mut MovingPtr`
1435
let mut ptr: $crate::MovingPtr<_, _> = $ptr;
1436
let _ = || {
1437
let value = &mut *ptr;
1438
// Ensure that each field index exists is mentioned only once
1439
// Ensure that each field is on the struct and not accessed using autoref
1440
let $struct_name { $($field_index: _),* } = value;
1441
// Ensure that the struct is not `repr(packed)` and that we may take references to fields
1442
core::hint::black_box(($(&mut value.$field_index),*));
1443
// Ensure that `ptr` is a `$struct_name` and not just something that derefs to it
1444
let value: *mut _ = value;
1445
// SAFETY: This closure is never called
1446
$struct_name { ..unsafe { value.read() } };
1447
};
1448
// SAFETY:
1449
// - `f` does a raw pointer offset, which always returns a non-null pointer to a field inside `T`
1450
// - The struct is not `repr(packed)`, since otherwise the block of code above would fail compilation
1451
// - `mem::forget` is called on `self` immediately after these calls
1452
// - Each field is distinct, since otherwise the block of code above would fail compilation
1453
$(let $crate::get_pattern!($field_index$(: $pattern)?) = unsafe { ptr.move_field(|f| &raw mut (*f).$field_index) };)*
1454
core::mem::forget(ptr);
1455
};
1456
({ let MaybeUninit::<$struct_name:ident> { $($field_index:tt$(: $pattern:pat)?),* $(,)? } = $ptr:expr ;}) => {
1457
// Specify the type to make sure the `mem::forget` doesn't forget a mere `&mut MovingPtr`
1458
let mut ptr: $crate::MovingPtr<core::mem::MaybeUninit<_>, _> = $ptr;
1459
let _ = || {
1460
// SAFETY: This closure is never called
1461
let value = unsafe { ptr.assume_init_mut() };
1462
// Ensure that each field index exists is mentioned only once
1463
// Ensure that each field is on the struct and not accessed using autoref
1464
let $struct_name { $($field_index: _),* } = value;
1465
// Ensure that the struct is not `repr(packed)` and that we may take references to fields
1466
core::hint::black_box(($(&mut value.$field_index),*));
1467
// Ensure that `ptr` is a `$struct_name` and not just something that derefs to it
1468
let value: *mut _ = value;
1469
// SAFETY: This closure is never called
1470
$struct_name { ..unsafe { value.read() } };
1471
};
1472
// SAFETY:
1473
// - `f` does a raw pointer offset, which always returns a non-null pointer to a field inside `T`
1474
// - The struct is not `repr(packed)`, since otherwise the block of code above would fail compilation
1475
// - `mem::forget` is called on `self` immediately after these calls
1476
// - Each field is distinct, since otherwise the block of code above would fail compilation
1477
$(let $crate::get_pattern!($field_index$(: $pattern)?) = unsafe { ptr.move_maybe_uninit_field(|f| &raw mut (*f).$field_index) };)*
1478
core::mem::forget(ptr);
1479
};
1480
}
1481
1482