Use Any for Resources instead of pointers, utility stuff for DynamicType
This commit is contained in:
parent
8c8e7dfd7d
commit
68a2868478
|
@ -49,16 +49,42 @@ impl Into<DynTypeId> for u128 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<TypeId> for DynTypeId {
|
impl Into<DynTypeId> for TypeId {
|
||||||
|
fn into(self) -> DynTypeId {
|
||||||
|
DynTypeId::Rust(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* impl From<TypeId> for DynTypeId {
|
||||||
fn from(value: TypeId) -> Self {
|
fn from(value: TypeId) -> Self {
|
||||||
DynTypeId::Rust(value)
|
DynTypeId::Rust(value)
|
||||||
}
|
}
|
||||||
}
|
} */
|
||||||
|
|
||||||
impl DynTypeId {
|
impl DynTypeId {
|
||||||
pub fn of<T: 'static>() -> Self {
|
pub fn of<T: 'static>() -> Self {
|
||||||
Self::Rust(TypeId::of::<T>())
|
Self::Rust(TypeId::of::<T>())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is<T: 'static>(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
DynTypeId::Rust(tyid) => tyid.clone() == TypeId::of::<T>(),
|
||||||
|
DynTypeId::Unknown(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_id<I: Into<DynTypeId>>(&self, id: I) -> bool {
|
||||||
|
let id = id.into();
|
||||||
|
*self == id
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Force self into a rust TypeId, will panic if this type is not a Rust type.
|
||||||
|
pub fn as_rust(&self) -> TypeId {
|
||||||
|
match self {
|
||||||
|
DynTypeId::Rust(t) => t.clone(),
|
||||||
|
DynTypeId::Unknown(_) => panic!("This type is unknown to rust, cannot construct a TypeId from it!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
@ -71,7 +97,7 @@ pub struct ComponentInfo {
|
||||||
impl ComponentInfo {
|
impl ComponentInfo {
|
||||||
pub fn new<T: 'static>() -> Self {
|
pub fn new<T: 'static>() -> Self {
|
||||||
Self {
|
Self {
|
||||||
type_id: DynTypeId::from(TypeId::of::<T>()),
|
type_id: TypeId::of::<T>().into(),
|
||||||
//name: type_name::<T>().to_string(),
|
//name: type_name::<T>().to_string(),
|
||||||
layout: MemoryLayout::from(Layout::new::<T>()),
|
layout: MemoryLayout::from(Layout::new::<T>()),
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,12 @@ pub struct DynamicType {
|
||||||
pub ptr: NonNull<u8>,
|
pub ptr: NonNull<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl DynamicType {
|
||||||
|
pub fn is<T: 'static>(&self) -> bool {
|
||||||
|
self.info.type_id.is::<T>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A struct that fetches some dynamic type.
|
/// A struct that fetches some dynamic type.
|
||||||
///
|
///
|
||||||
/// Currently it can only fetch from archetypes, later it will be able to fetch dynamic
|
/// Currently it can only fetch from archetypes, later it will be able to fetch dynamic
|
||||||
|
|
|
@ -42,7 +42,7 @@ impl<'a> IntoIterator for DynamicView<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DynamicViewIter<'a> {
|
pub struct DynamicViewIter<'a> {
|
||||||
world: &'a World,
|
pub world: &'a World,
|
||||||
queries: Vec<QueryDynamicType>,
|
queries: Vec<QueryDynamicType>,
|
||||||
fetchers: Vec<FetchDynamicType<'a>>,
|
fetchers: Vec<FetchDynamicType<'a>>,
|
||||||
archetypes: Vec<&'a Archetype>,
|
archetypes: Vec<&'a Archetype>,
|
||||||
|
|
|
@ -1,79 +1,58 @@
|
||||||
use std::{any::TypeId, alloc::Layout, cell::{RefCell, Ref, RefMut}, ptr::NonNull, alloc};
|
use std::{any::{TypeId, Any}, alloc::Layout, cell::{RefCell, Ref, RefMut}, ptr::NonNull, alloc};
|
||||||
|
|
||||||
/// Shorthand for `Send + Sync + 'static`, so it never needs to be implemented manually.
|
/// Shorthand for `Send + Sync + 'static`, so it never needs to be implemented manually.
|
||||||
pub trait ResourceObject: Send + Sync + 'static {}
|
pub trait ResourceObject: Send + Sync + 'static {}
|
||||||
impl<T: Send + Sync + 'static> ResourceObject for T {}
|
impl<T: Send + Sync + 'static> ResourceObject for T {}
|
||||||
|
|
||||||
/// A type erased storage for a Resource.
|
/// A type erased storage for a Resource.
|
||||||
///
|
|
||||||
/// A pointer instead of a generic is used since Rust may have no idea of the type of the data.
|
|
||||||
pub struct ResourceData {
|
pub struct ResourceData {
|
||||||
data: RefCell<NonNull<u8>>,
|
data: Box<RefCell<dyn Any>>,
|
||||||
type_id: TypeId,
|
type_id: TypeId,
|
||||||
layout: Layout,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ResourceData {
|
impl ResourceData {
|
||||||
pub fn new<T: 'static>(data: T) -> Self {
|
pub fn new<T: Any>(data: T) -> Self {
|
||||||
let layout = Layout::new::<T>();
|
|
||||||
let data = NonNull::from(&data).cast();
|
|
||||||
|
|
||||||
let ptr = unsafe {
|
|
||||||
if let Some(ptr) = NonNull::new(alloc::alloc(layout)) {
|
|
||||||
std::ptr::copy_nonoverlapping(data.as_ptr(), ptr.as_ptr(), layout.size());
|
|
||||||
ptr
|
|
||||||
} else {
|
|
||||||
alloc::handle_alloc_error(layout)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
data: RefCell::new(ptr),
|
data: Box::new(RefCell::new(data)),
|
||||||
type_id: TypeId::of::<T>(),
|
type_id: TypeId::of::<T>(),
|
||||||
layout,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a boolean indicating whether or not T is of the same type that is inside this Resource
|
/// Returns a boolean indicating whether or not `T`` is of the same type of the Resource
|
||||||
pub fn is<T: 'static>(&self) -> bool {
|
pub fn is<T: 'static>(&self) -> bool {
|
||||||
self.type_id == TypeId::of::<T>()
|
self.type_id == TypeId::of::<T>()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Borrow the data inside of the resource.
|
/// Borrow the data inside of the resource.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// If the type of T is not the same as the expected type, it will panic.
|
/// * If the data is already borrowed mutably, this will panic.
|
||||||
|
/// * If the type of `T` is not the same as the resource type.
|
||||||
pub fn get<'a, T: 'static>(&'a self) -> Ref<'a, T> {
|
pub fn get<'a, T: 'static>(&'a self) -> Ref<'a, T> {
|
||||||
assert!(TypeId::of::<T>() == self.type_id);
|
Ref::map(self.data.borrow(), |a| a.downcast_ref().unwrap())
|
||||||
|
|
||||||
let data = self.data.borrow();
|
|
||||||
Ref::map(data, |ptr| unsafe { &*ptr.cast().as_ptr() })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mutably borrow the data inside of the resource.
|
/// Mutably borrow the data inside of the resource.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// * If the type of T is not the same as the expected type, it will panic.
|
|
||||||
/// * If the data is already borrowed mutably, this will panic.
|
/// * If the data is already borrowed mutably, this will panic.
|
||||||
|
/// * If the type of `T` is not the same as the resource type.
|
||||||
pub fn get_mut<'a, T: 'static>(&'a self) -> RefMut<'a, T> {
|
pub fn get_mut<'a, T: 'static>(&'a self) -> RefMut<'a, T> {
|
||||||
assert!(TypeId::of::<T>() == self.type_id);
|
RefMut::map(self.data.borrow_mut(), |a| a.downcast_mut().unwrap())
|
||||||
|
|
||||||
let data = self.data.borrow_mut();
|
|
||||||
RefMut::map(data, |ptr| unsafe { &mut *ptr.cast().as_ptr() })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Borrow the data inside of the resource.
|
/// Borrow the data inside of the resource.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// If the type of T is not the same as the expected type, it will panic.
|
/// * If the type of `T` is not the same as the resource type.
|
||||||
pub fn try_get<'a, T: 'static>(&'a self) -> Option<Ref<'a, T>> {
|
pub fn try_get<'a, T: 'static>(&'a self) -> Option<Ref<'a, T>> {
|
||||||
assert!(TypeId::of::<T>() == self.type_id);
|
|
||||||
|
|
||||||
self.data.try_borrow()
|
self.data.try_borrow()
|
||||||
.map(|r| Ref::map(r, |ptr| unsafe { &*ptr.cast().as_ptr() }))
|
.map(|r| Ref::map(r, |a| a.downcast_ref().unwrap()))
|
||||||
.ok()
|
.ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,13 +60,10 @@ impl ResourceData {
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// * If the type of T is not the same as the expected type, it will panic.
|
/// * If the type of `T` is not the same as the resource type.
|
||||||
/// * If the data is already borrowed mutably, this will panic.
|
|
||||||
pub fn try_get_mut<'a, T: 'static>(&'a self) -> Option<RefMut<'a, T>> {
|
pub fn try_get_mut<'a, T: 'static>(&'a self) -> Option<RefMut<'a, T>> {
|
||||||
assert!(TypeId::of::<T>() == self.type_id);
|
|
||||||
|
|
||||||
self.data.try_borrow_mut()
|
self.data.try_borrow_mut()
|
||||||
.map(|r| RefMut::map(r, |ptr| unsafe { &mut *ptr.cast().as_ptr() }))
|
.map(|r| RefMut::map(r, |a| a.downcast_mut().unwrap()))
|
||||||
.ok()
|
.ok()
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue