mirror of
https://github.com/bevyengine/bevy
synced 2024-11-25 06:00:20 +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"]
|
default = ["bevy_reflect"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
bevy_ptr = { path = "../bevy_ptr", version = "0.8.0-dev" }
|
||||||
bevy_reflect = { path = "../bevy_reflect", version = "0.8.0-dev", optional = true }
|
bevy_reflect = { path = "../bevy_reflect", version = "0.8.0-dev", optional = true }
|
||||||
bevy_tasks = { path = "../bevy_tasks", version = "0.8.0-dev" }
|
bevy_tasks = { path = "../bevy_tasks", version = "0.8.0-dev" }
|
||||||
bevy_utils = { path = "../bevy_utils", 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},
|
archetype::{AddBundle, Archetype, ArchetypeId, Archetypes, ComponentStatus},
|
||||||
component::{Component, ComponentId, ComponentTicks, Components, StorageType},
|
component::{Component, ComponentId, ComponentTicks, Components, StorageType},
|
||||||
entity::{Entities, Entity, EntityLocation},
|
entity::{Entities, Entity, EntityLocation},
|
||||||
ptr::OwningPtr,
|
|
||||||
storage::{SparseSetIndex, SparseSets, Storages, Table},
|
storage::{SparseSetIndex, SparseSets, Storages, Table},
|
||||||
};
|
};
|
||||||
use bevy_ecs_macros::all_tuples;
|
use bevy_ecs_macros::all_tuples;
|
||||||
|
use bevy_ptr::OwningPtr;
|
||||||
use std::{any::TypeId, collections::HashMap};
|
use std::{any::TypeId, collections::HashMap};
|
||||||
|
|
||||||
/// An ordered collection of [`Component`]s.
|
/// An ordered collection of [`Component`]s.
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
//! Types for declaring and storing [`Component`]s.
|
//! Types for declaring and storing [`Component`]s.
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ptr::OwningPtr,
|
|
||||||
storage::{SparseSetIndex, Storages},
|
storage::{SparseSetIndex, Storages},
|
||||||
system::Resource,
|
system::Resource,
|
||||||
};
|
};
|
||||||
pub use bevy_ecs_macros::Component;
|
pub use bevy_ecs_macros::Component;
|
||||||
|
use bevy_ptr::OwningPtr;
|
||||||
use std::{
|
use std::{
|
||||||
alloc::Layout,
|
alloc::Layout,
|
||||||
any::{Any, TypeId},
|
any::{Any, TypeId},
|
||||||
|
|
|
@ -6,7 +6,6 @@ pub mod change_detection;
|
||||||
pub mod component;
|
pub mod component;
|
||||||
pub mod entity;
|
pub mod entity;
|
||||||
pub mod event;
|
pub mod event;
|
||||||
pub mod ptr;
|
|
||||||
pub mod query;
|
pub mod query;
|
||||||
#[cfg(feature = "bevy_reflect")]
|
#[cfg(feature = "bevy_reflect")]
|
||||||
pub mod reflect;
|
pub mod reflect;
|
||||||
|
@ -15,6 +14,8 @@ pub mod storage;
|
||||||
pub mod system;
|
pub mod system;
|
||||||
pub mod world;
|
pub mod world;
|
||||||
|
|
||||||
|
pub use bevy_ptr as ptr;
|
||||||
|
|
||||||
/// Most commonly used re-exported types.
|
/// Most commonly used re-exported types.
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
|
|
@ -3,13 +3,13 @@ use crate::{
|
||||||
change_detection::Ticks,
|
change_detection::Ticks,
|
||||||
component::{Component, ComponentId, ComponentStorage, ComponentTicks, StorageType},
|
component::{Component, ComponentId, ComponentStorage, ComponentTicks, StorageType},
|
||||||
entity::Entity,
|
entity::Entity,
|
||||||
ptr::{ThinSlicePtr, UnsafeCellDeref},
|
|
||||||
query::{debug_checked_unreachable, Access, FilteredAccess},
|
query::{debug_checked_unreachable, Access, FilteredAccess},
|
||||||
storage::{ComponentSparseSet, Table, Tables},
|
storage::{ComponentSparseSet, Table, Tables},
|
||||||
world::{Mut, World},
|
world::{Mut, World},
|
||||||
};
|
};
|
||||||
use bevy_ecs_macros::all_tuples;
|
use bevy_ecs_macros::all_tuples;
|
||||||
pub use bevy_ecs_macros::WorldQuery;
|
pub use bevy_ecs_macros::WorldQuery;
|
||||||
|
use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref};
|
||||||
use std::{cell::UnsafeCell, marker::PhantomData};
|
use std::{cell::UnsafeCell, marker::PhantomData};
|
||||||
|
|
||||||
/// Types that can be queried from a [`World`].
|
/// Types that can be queried from a [`World`].
|
||||||
|
|
|
@ -2,7 +2,6 @@ use crate::{
|
||||||
archetype::{Archetype, ArchetypeComponentId},
|
archetype::{Archetype, ArchetypeComponentId},
|
||||||
component::{Component, ComponentId, ComponentStorage, ComponentTicks, StorageType},
|
component::{Component, ComponentId, ComponentStorage, ComponentTicks, StorageType},
|
||||||
entity::Entity,
|
entity::Entity,
|
||||||
ptr::{ThinSlicePtr, UnsafeCellDeref},
|
|
||||||
query::{
|
query::{
|
||||||
debug_checked_unreachable, Access, Fetch, FetchState, FilteredAccess, QueryFetch,
|
debug_checked_unreachable, Access, Fetch, FetchState, FilteredAccess, QueryFetch,
|
||||||
ROQueryFetch, WorldQuery, WorldQueryGats,
|
ROQueryFetch, WorldQuery, WorldQueryGats,
|
||||||
|
@ -11,6 +10,7 @@ use crate::{
|
||||||
world::World,
|
world::World,
|
||||||
};
|
};
|
||||||
use bevy_ecs_macros::all_tuples;
|
use bevy_ecs_macros::all_tuples;
|
||||||
|
use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref};
|
||||||
use std::{cell::UnsafeCell, marker::PhantomData};
|
use std::{cell::UnsafeCell, marker::PhantomData};
|
||||||
|
|
||||||
use super::ReadOnlyFetch;
|
use super::ReadOnlyFetch;
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::{
|
||||||
ptr::NonNull,
|
ptr::NonNull,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::ptr::{OwningPtr, Ptr, PtrMut};
|
use bevy_ptr::{OwningPtr, Ptr, PtrMut};
|
||||||
|
|
||||||
/// A flat, type-erased data storage type
|
/// A flat, type-erased data storage type
|
||||||
///
|
///
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
component::{ComponentId, ComponentInfo, ComponentTicks},
|
component::{ComponentId, ComponentInfo, ComponentTicks},
|
||||||
entity::Entity,
|
entity::Entity,
|
||||||
ptr::{OwningPtr, Ptr},
|
|
||||||
storage::BlobVec,
|
storage::BlobVec,
|
||||||
};
|
};
|
||||||
|
use bevy_ptr::{OwningPtr, Ptr};
|
||||||
use std::{cell::UnsafeCell, marker::PhantomData};
|
use std::{cell::UnsafeCell, marker::PhantomData};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
component::{ComponentId, ComponentInfo, ComponentTicks, Components},
|
component::{ComponentId, ComponentInfo, ComponentTicks, Components},
|
||||||
entity::Entity,
|
entity::Entity,
|
||||||
ptr::{OwningPtr, Ptr, PtrMut},
|
|
||||||
storage::{BlobVec, SparseSet},
|
storage::{BlobVec, SparseSet},
|
||||||
};
|
};
|
||||||
|
use bevy_ptr::{OwningPtr, Ptr, PtrMut};
|
||||||
use bevy_utils::HashMap;
|
use bevy_utils::HashMap;
|
||||||
use std::{
|
use std::{
|
||||||
cell::UnsafeCell,
|
cell::UnsafeCell,
|
||||||
|
|
|
@ -5,7 +5,6 @@ use crate::{
|
||||||
change_detection::Ticks,
|
change_detection::Ticks,
|
||||||
component::{Component, ComponentId, ComponentTicks, Components},
|
component::{Component, ComponentId, ComponentTicks, Components},
|
||||||
entity::{Entities, Entity},
|
entity::{Entities, Entity},
|
||||||
ptr::UnsafeCellDeref,
|
|
||||||
query::{
|
query::{
|
||||||
Access, FilteredAccess, FilteredAccessSet, QueryFetch, QueryState, ReadOnlyFetch,
|
Access, FilteredAccess, FilteredAccessSet, QueryFetch, QueryState, ReadOnlyFetch,
|
||||||
WorldQuery,
|
WorldQuery,
|
||||||
|
@ -15,6 +14,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
pub use bevy_ecs_macros::SystemParam;
|
pub use bevy_ecs_macros::SystemParam;
|
||||||
use bevy_ecs_macros::{all_tuples, impl_param_set};
|
use bevy_ecs_macros::{all_tuples, impl_param_set};
|
||||||
|
use bevy_ptr::UnsafeCellDeref;
|
||||||
use std::{
|
use std::{
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
|
|
|
@ -4,10 +4,10 @@ use crate::{
|
||||||
change_detection::Ticks,
|
change_detection::Ticks,
|
||||||
component::{Component, ComponentId, ComponentTicks, Components, StorageType},
|
component::{Component, ComponentId, ComponentTicks, Components, StorageType},
|
||||||
entity::{Entities, Entity, EntityLocation},
|
entity::{Entities, Entity, EntityLocation},
|
||||||
ptr::{OwningPtr, Ptr, UnsafeCellDeref},
|
|
||||||
storage::{SparseSet, Storages},
|
storage::{SparseSet, Storages},
|
||||||
world::{Mut, World},
|
world::{Mut, World},
|
||||||
};
|
};
|
||||||
|
use bevy_ptr::{OwningPtr, Ptr, UnsafeCellDeref};
|
||||||
use std::{any::TypeId, cell::UnsafeCell};
|
use std::{any::TypeId, cell::UnsafeCell};
|
||||||
|
|
||||||
/// A read-only reference to a particular [`Entity`] and all of its components
|
/// A read-only reference to a particular [`Entity`] and all of its components
|
||||||
|
|
|
@ -13,11 +13,11 @@ use crate::{
|
||||||
change_detection::Ticks,
|
change_detection::Ticks,
|
||||||
component::{Component, ComponentId, ComponentTicks, Components, StorageType},
|
component::{Component, ComponentId, ComponentTicks, Components, StorageType},
|
||||||
entity::{AllocAtWithoutReplacement, Entities, Entity},
|
entity::{AllocAtWithoutReplacement, Entities, Entity},
|
||||||
ptr::{OwningPtr, UnsafeCellDeref},
|
|
||||||
query::{QueryState, WorldQuery},
|
query::{QueryState, WorldQuery},
|
||||||
storage::{Column, SparseSet, Storages},
|
storage::{Column, SparseSet, Storages},
|
||||||
system::Resource,
|
system::Resource,
|
||||||
};
|
};
|
||||||
|
use bevy_ptr::{OwningPtr, UnsafeCellDeref};
|
||||||
use bevy_utils::tracing::debug;
|
use bevy_utils::tracing::debug;
|
||||||
use std::{
|
use std::{
|
||||||
any::TypeId,
|
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_input = { path = "../bevy_input", version = "0.8.0-dev" }
|
||||||
bevy_log = { path = "../bevy_log", 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_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_reflect = { path = "../bevy_reflect", version = "0.8.0-dev", features = ["bevy"] }
|
||||||
bevy_scene = { path = "../bevy_scene", version = "0.8.0-dev" }
|
bevy_scene = { path = "../bevy_scene", version = "0.8.0-dev" }
|
||||||
bevy_transform = { path = "../bevy_transform", 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 use bevy_math::*;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod ptr {
|
||||||
|
//! Utilities for working with untyped pointers in a more safe way.
|
||||||
|
pub use bevy_ptr::*;
|
||||||
|
}
|
||||||
|
|
||||||
pub mod reflect {
|
pub mod reflect {
|
||||||
// TODO: remove these renames once TypeRegistryArc is no longer required
|
// TODO: remove these renames once TypeRegistryArc is no longer required
|
||||||
//! Type reflection used for dynamically interacting with rust types.
|
//! 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};
|
use std::{cell::UnsafeCell, marker::PhantomData, mem::MaybeUninit, ptr::NonNull};
|
||||||
|
|
||||||
/// Type-erased borrow of some unknown type chosen when constructing this type.
|
/// 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;
|
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;
|
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
|
unsafe fn read(self) -> T
|
||||||
where
|
where
|
||||||
T: Copy;
|
T: Copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> UnsafeCellDeref<'a, T> for &'a UnsafeCell<T> {
|
impl<'a, T> UnsafeCellDeref<'a, T> for &'a UnsafeCell<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn deref_mut(self) -> &'a mut T {
|
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
|
# if crate A depends on crate B, B must come before A in this list
|
||||||
crates=(
|
crates=(
|
||||||
bevy_utils
|
bevy_utils
|
||||||
|
bevy_ptr
|
||||||
bevy_macro_utils
|
bevy_macro_utils
|
||||||
bevy_derive
|
bevy_derive
|
||||||
bevy_math
|
bevy_math
|
||||||
|
|
Loading…
Reference in a new issue