Round out the untyped api s (#7009)

# Objective

Bevy uses custom `Ptr` types so the rust borrow checker can help ensure lifetimes are correct, even when types aren't known. However, these types don't benefit from the automatic lifetime coercion regular rust references enjoy

## Solution

Add a couple methods to Ptr, PtrMut, and MutUntyped to allow for easy usage of these types in more complex scenarios.

## Changelog

- Added `as_mut` and `as_ref` methods to `MutUntyped`.
- Added `shrink` and `as_ref` methods to `PtrMut`.

## Migration Guide

- `MutUntyped::into_inner` now marks things as changed.
This commit is contained in:
Nile 2022-12-27 16:05:16 +00:00
parent ca85f6c903
commit 0ddaa7e83a
2 changed files with 48 additions and 4 deletions

View file

@ -5,7 +5,7 @@ use crate::{
ptr::PtrMut,
system::Resource,
};
use bevy_ptr::UnsafeCellDeref;
use bevy_ptr::{Ptr, UnsafeCellDeref};
use std::ops::{Deref, DerefMut};
/// The (arbitrarily chosen) minimum number of world tick increments between `check_tick` scans.
@ -421,13 +421,29 @@ pub struct MutUntyped<'a> {
}
impl<'a> MutUntyped<'a> {
/// Returns the pointer to the value, without marking it as changed.
/// Returns the pointer to the value, marking it as changed.
///
/// In order to mark the value as changed, you need to call [`set_changed`](DetectChanges::set_changed) manually.
/// In order to avoid marking the value as changed, you need to call [`bypass_change_detection`](DetectChanges::bypass_change_detection).
#[inline]
pub fn into_inner(self) -> PtrMut<'a> {
pub fn into_inner(mut self) -> PtrMut<'a> {
self.set_changed();
self.value
}
/// Returns a pointer to the value without taking ownership of this smart pointer, marking it as changed.
///
/// In order to avoid marking the value as changed, you need to call [`bypass_change_detection`](DetectChanges::bypass_change_detection).
#[inline]
pub fn as_mut(&mut self) -> PtrMut<'_> {
self.set_changed();
self.value.reborrow()
}
/// Returns an immutable pointer to the value without taking ownership.
#[inline]
pub fn as_ref(&self) -> Ptr<'_> {
self.value.as_ref()
}
}
impl<'a> DetectChanges for MutUntyped<'a> {

View file

@ -176,6 +176,20 @@ impl<'a> PtrMut<'a> {
pub fn as_ptr(&self) -> *mut u8 {
self.0.as_ptr()
}
/// Gets a `PtrMut` from this with a smaller lifetime.
#[inline]
pub fn reborrow(&mut self) -> PtrMut<'_> {
// SAFE: the ptrmut we're borrowing from is assumed to be valid
unsafe { PtrMut::new(self.0) }
}
/// Gets an immutable reference from this mutable reference
#[inline]
pub fn as_ref(&self) -> Ptr<'_> {
// SAFE: The `PtrMut` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees
unsafe { Ptr::new(self.0) }
}
}
impl<'a, T> From<&'a mut T> for PtrMut<'a> {
@ -224,6 +238,20 @@ impl<'a> OwningPtr<'a> {
pub fn as_ptr(&self) -> *mut u8 {
self.0.as_ptr()
}
/// Gets an immutable pointer from this owned pointer.
#[inline]
pub fn as_ref(&self) -> Ptr<'_> {
// SAFE: The `Owning` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees
unsafe { Ptr::new(self.0) }
}
/// Gets a mutable pointer from this owned pointer.
#[inline]
pub fn as_mut(&mut self) -> PtrMut<'_> {
// SAFE: The `Owning` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees
unsafe { PtrMut::new(self.0) }
}
}
/// Conceptually equivalent to `&'a [T]` but with length information cut out for performance reasons