mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
bevy_ptr
standalone crate (#4653)
# Objective The pointer types introduced in #3001 are useful not just in `bevy_ecs`, but also in crates like `bevy_reflect` (#4475) or even outside of bevy. ## Solution Extract `Ptr<'a>`, `PtrMut<'a>`, `OwnedPtr<'a>`, `ThinSlicePtr<'a, T>` and `UnsafeCellDeref` from `bevy_ecs::ptr` into `bevy_ptr`. **Note:** `bevy_ecs` still reexports the `bevy_ptr` as `bevy_ecs::ptr` so that crates like `bevy_transform` can use the `Bundle` derive without needing to depend on `bevy_ptr` themselves.
This commit is contained in:
parent
9d440fbcb5
commit
1e322d9f76
18 changed files with 62 additions and 12 deletions
|
@ -14,6 +14,7 @@ trace = []
|
|||
default = ["bevy_reflect"]
|
||||
|
||||
[dependencies]
|
||||
bevy_ptr = { path = "../bevy_ptr", version = "0.8.0-dev" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.8.0-dev", optional = true }
|
||||
bevy_tasks = { path = "../bevy_tasks", version = "0.8.0-dev" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.8.0-dev" }
|
||||
|
|
|
@ -8,10 +8,10 @@ use crate::{
|
|||
archetype::{AddBundle, Archetype, ArchetypeId, Archetypes, ComponentStatus},
|
||||
component::{Component, ComponentId, ComponentTicks, Components, StorageType},
|
||||
entity::{Entities, Entity, EntityLocation},
|
||||
ptr::OwningPtr,
|
||||
storage::{SparseSetIndex, SparseSets, Storages, Table},
|
||||
};
|
||||
use bevy_ecs_macros::all_tuples;
|
||||
use bevy_ptr::OwningPtr;
|
||||
use std::{any::TypeId, collections::HashMap};
|
||||
|
||||
/// An ordered collection of [`Component`]s.
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
//! Types for declaring and storing [`Component`]s.
|
||||
|
||||
use crate::{
|
||||
ptr::OwningPtr,
|
||||
storage::{SparseSetIndex, Storages},
|
||||
system::Resource,
|
||||
};
|
||||
pub use bevy_ecs_macros::Component;
|
||||
use bevy_ptr::OwningPtr;
|
||||
use std::{
|
||||
alloc::Layout,
|
||||
any::{Any, TypeId},
|
||||
|
|
|
@ -6,7 +6,6 @@ pub mod change_detection;
|
|||
pub mod component;
|
||||
pub mod entity;
|
||||
pub mod event;
|
||||
pub mod ptr;
|
||||
pub mod query;
|
||||
#[cfg(feature = "bevy_reflect")]
|
||||
pub mod reflect;
|
||||
|
@ -15,6 +14,8 @@ pub mod storage;
|
|||
pub mod system;
|
||||
pub mod world;
|
||||
|
||||
pub use bevy_ptr as ptr;
|
||||
|
||||
/// Most commonly used re-exported types.
|
||||
pub mod prelude {
|
||||
#[doc(hidden)]
|
||||
|
|
|
@ -3,13 +3,13 @@ use crate::{
|
|||
change_detection::Ticks,
|
||||
component::{Component, ComponentId, ComponentStorage, ComponentTicks, StorageType},
|
||||
entity::Entity,
|
||||
ptr::{ThinSlicePtr, UnsafeCellDeref},
|
||||
query::{debug_checked_unreachable, Access, FilteredAccess},
|
||||
storage::{ComponentSparseSet, Table, Tables},
|
||||
world::{Mut, World},
|
||||
};
|
||||
use bevy_ecs_macros::all_tuples;
|
||||
pub use bevy_ecs_macros::WorldQuery;
|
||||
use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref};
|
||||
use std::{cell::UnsafeCell, marker::PhantomData};
|
||||
|
||||
/// Types that can be queried from a [`World`].
|
||||
|
|
|
@ -2,7 +2,6 @@ use crate::{
|
|||
archetype::{Archetype, ArchetypeComponentId},
|
||||
component::{Component, ComponentId, ComponentStorage, ComponentTicks, StorageType},
|
||||
entity::Entity,
|
||||
ptr::{ThinSlicePtr, UnsafeCellDeref},
|
||||
query::{
|
||||
debug_checked_unreachable, Access, Fetch, FetchState, FilteredAccess, QueryFetch,
|
||||
ROQueryFetch, WorldQuery, WorldQueryGats,
|
||||
|
@ -11,6 +10,7 @@ use crate::{
|
|||
world::World,
|
||||
};
|
||||
use bevy_ecs_macros::all_tuples;
|
||||
use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref};
|
||||
use std::{cell::UnsafeCell, marker::PhantomData};
|
||||
|
||||
use super::ReadOnlyFetch;
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::{
|
|||
ptr::NonNull,
|
||||
};
|
||||
|
||||
use crate::ptr::{OwningPtr, Ptr, PtrMut};
|
||||
use bevy_ptr::{OwningPtr, Ptr, PtrMut};
|
||||
|
||||
/// A flat, type-erased data storage type
|
||||
///
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use crate::{
|
||||
component::{ComponentId, ComponentInfo, ComponentTicks},
|
||||
entity::Entity,
|
||||
ptr::{OwningPtr, Ptr},
|
||||
storage::BlobVec,
|
||||
};
|
||||
use bevy_ptr::{OwningPtr, Ptr};
|
||||
use std::{cell::UnsafeCell, marker::PhantomData};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use crate::{
|
||||
component::{ComponentId, ComponentInfo, ComponentTicks, Components},
|
||||
entity::Entity,
|
||||
ptr::{OwningPtr, Ptr, PtrMut},
|
||||
storage::{BlobVec, SparseSet},
|
||||
};
|
||||
use bevy_ptr::{OwningPtr, Ptr, PtrMut};
|
||||
use bevy_utils::HashMap;
|
||||
use std::{
|
||||
cell::UnsafeCell,
|
||||
|
|
|
@ -5,7 +5,6 @@ use crate::{
|
|||
change_detection::Ticks,
|
||||
component::{Component, ComponentId, ComponentTicks, Components},
|
||||
entity::{Entities, Entity},
|
||||
ptr::UnsafeCellDeref,
|
||||
query::{
|
||||
Access, FilteredAccess, FilteredAccessSet, QueryFetch, QueryState, ReadOnlyFetch,
|
||||
WorldQuery,
|
||||
|
@ -15,6 +14,7 @@ use crate::{
|
|||
};
|
||||
pub use bevy_ecs_macros::SystemParam;
|
||||
use bevy_ecs_macros::{all_tuples, impl_param_set};
|
||||
use bevy_ptr::UnsafeCellDeref;
|
||||
use std::{
|
||||
fmt::Debug,
|
||||
marker::PhantomData,
|
||||
|
|
|
@ -4,10 +4,10 @@ use crate::{
|
|||
change_detection::Ticks,
|
||||
component::{Component, ComponentId, ComponentTicks, Components, StorageType},
|
||||
entity::{Entities, Entity, EntityLocation},
|
||||
ptr::{OwningPtr, Ptr, UnsafeCellDeref},
|
||||
storage::{SparseSet, Storages},
|
||||
world::{Mut, World},
|
||||
};
|
||||
use bevy_ptr::{OwningPtr, Ptr, UnsafeCellDeref};
|
||||
use std::{any::TypeId, cell::UnsafeCell};
|
||||
|
||||
/// A read-only reference to a particular [`Entity`] and all of its components
|
||||
|
|
|
@ -13,11 +13,11 @@ use crate::{
|
|||
change_detection::Ticks,
|
||||
component::{Component, ComponentId, ComponentTicks, Components, StorageType},
|
||||
entity::{AllocAtWithoutReplacement, Entities, Entity},
|
||||
ptr::{OwningPtr, UnsafeCellDeref},
|
||||
query::{QueryState, WorldQuery},
|
||||
storage::{Column, SparseSet, Storages},
|
||||
system::Resource,
|
||||
};
|
||||
use bevy_ptr::{OwningPtr, UnsafeCellDeref};
|
||||
use bevy_utils::tracing::debug;
|
||||
use std::{
|
||||
any::TypeId,
|
||||
|
|
|
@ -75,6 +75,7 @@ bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.8.0-dev" }
|
|||
bevy_input = { path = "../bevy_input", version = "0.8.0-dev" }
|
||||
bevy_log = { path = "../bevy_log", version = "0.8.0-dev" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.8.0-dev" }
|
||||
bevy_ptr = { path = "../bevy_ptr", version = "0.8.0-dev" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.8.0-dev", features = ["bevy"] }
|
||||
bevy_scene = { path = "../bevy_scene", version = "0.8.0-dev" }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.8.0-dev" }
|
||||
|
|
|
@ -47,6 +47,11 @@ pub mod math {
|
|||
pub use bevy_math::*;
|
||||
}
|
||||
|
||||
pub mod ptr {
|
||||
//! Utilities for working with untyped pointers in a more safe way.
|
||||
pub use bevy_ptr::*;
|
||||
}
|
||||
|
||||
pub mod reflect {
|
||||
// TODO: remove these renames once TypeRegistryArc is no longer required
|
||||
//! Type reflection used for dynamically interacting with rust types.
|
||||
|
|
11
crates/bevy_ptr/Cargo.toml
Normal file
11
crates/bevy_ptr/Cargo.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "bevy_ptr"
|
||||
version = "0.8.0-dev"
|
||||
edition = "2021"
|
||||
description = "Utilities for working with untyped pointers in a more safe way"
|
||||
homepage = "https://bevyengine.org"
|
||||
repository = "https://github.com/bevyengine/bevy"
|
||||
license = "MIT OR Apache-2.0"
|
||||
keywords = ["bevy"]
|
||||
|
||||
[dependencies]
|
7
crates/bevy_ptr/README.md
Normal file
7
crates/bevy_ptr/README.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
# `bevy_ptr`
|
||||
|
||||
The `bevy_ptr` crate provides low-level abstractions for working with pointers in a more safe way than using rust's raw pointers.
|
||||
|
||||
Rust has lifetimed and typed references (`&'a T`), unlifetimed and typed references (`*const T`), but no lifetimed but untyped references.
|
||||
`bevy_ptr` adds them, called `Ptr<'a>`, `PtrMut<'a>` and `OwningPtr<'a>`.
|
||||
These types are lifetime-checked so can never lead to problems like use-after-frees and must always point to valid data.
|
|
@ -1,3 +1,4 @@
|
|||
#![doc = include_str!("../README.md")]
|
||||
use std::{cell::UnsafeCell, marker::PhantomData, mem::MaybeUninit, ptr::NonNull};
|
||||
|
||||
/// Type-erased borrow of some unknown type chosen when constructing this type.
|
||||
|
@ -249,13 +250,35 @@ impl<'a, T> From<&'a [T]> for ThinSlicePtr<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) trait UnsafeCellDeref<'a, T> {
|
||||
mod private {
|
||||
use std::cell::UnsafeCell;
|
||||
|
||||
pub trait SealedUnsafeCell {}
|
||||
impl<'a, T> SealedUnsafeCell for &'a UnsafeCell<T> {}
|
||||
}
|
||||
|
||||
/// Extension trait for helper methods on [`UnsafeCell`]
|
||||
pub trait UnsafeCellDeref<'a, T>: private::SealedUnsafeCell {
|
||||
/// # Safety
|
||||
/// - The returned value must be unique and not alias any mutable or immutable references to the contents of the [`UnsafeCell`].
|
||||
/// - 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).
|
||||
unsafe fn deref_mut(self) -> &'a mut T;
|
||||
|
||||
/// # Safety
|
||||
/// - For the lifetime `'a` of the returned value you must not construct a mutable reference to the contents of the [`UnsafeCell`].
|
||||
/// - 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).
|
||||
unsafe fn deref(self) -> &'a T;
|
||||
|
||||
/// Returns a copy of the contained value.
|
||||
///
|
||||
/// # Safety
|
||||
/// - The [`UnsafeCell`] must not currently have a mutable reference to its content.
|
||||
/// - 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).
|
||||
unsafe fn read(self) -> T
|
||||
where
|
||||
T: Copy;
|
||||
}
|
||||
|
||||
impl<'a, T> UnsafeCellDeref<'a, T> for &'a UnsafeCell<T> {
|
||||
#[inline]
|
||||
unsafe fn deref_mut(self) -> &'a mut T {
|
|
@ -1,6 +1,7 @@
|
|||
# if crate A depends on crate B, B must come before A in this list
|
||||
crates=(
|
||||
bevy_utils
|
||||
bevy_ptr
|
||||
bevy_macro_utils
|
||||
bevy_derive
|
||||
bevy_math
|
||||
|
|
Loading…
Reference in a new issue